您好,欢迎访问一九零五行业门户网

String使用equals方法和==分别比较的是什么

equals方法和==的区别
  首先大家知道,string既可以作为一个对象来使用,又可以作为一个基本类型来使用。这里指的作为一个基本类型来使用只是指使用方法上的,比如string s = hello,它的使用方法如同基本类型int一样,比如int i = 1;,而作为一个对象来使用,则是指通过new关键字来创建一个新对象,比如string s = new string(hello)。但是它的内部动作其实还是创建了一个对象,这点稍后会说到。
        其次,对string对象的比较方法需要了解。java里对象之间的比较有两种概念,这里拿string对象来说:一种是用==来比较,这种比较是针对两个string类型的变量的引用,也就是说如果两个string类型的变量,它们所引用同一个string对象(即指向同一块内存堆),则==比较的结果是true。另一种是用object对象的equals()方法来比较,string对象继承自object,并且对equals()方法进行了重写。两个string对象通过equals()方法来进行比较时,其实就是对string对象所封装的字符串内容进行比较,也就是说如果两个string对象所封装的字符串内容相同(包括大小写相同),则equals()方法将返回true。
现在开始将对string对象的创建做具体的分析:
1、/////////////////////////////////////////////////////////////////////////
string s1 = new string(hello);
string s2 = new string(hello);
system.out.println(s1 == s2);
system.out.println(s1.equals(s2));
以上代码段的打印结果是:
false
true
        这个结果相信大家很好理解,两个string类型的变量s1和s2都通过new关键字分别创建了一个新的string对象,这个new关键字为创建的每个对象分配一块新的、独立的内存堆。因此当通过==来比较它们所引用的是否是同一个对象时,将返回false。而通过equals()方法来比较时,则返回true,因为这两个对象所封装的字符串内容是完全相同的。
2、//////////////////////////////////////////////////////////////////////////////////
string s1 = new string(hello);
string s2 = s1;
system.out.println(s1 == s2);
system.out.println(s1.equals(s2));
以上代码段的打印结果是:
true
true
        这个结果应该更好理解,变量s1还是通过new关键字来创建了一个新的string对象,但这里s2并没有通过new关键字来创建一个新的string对象,而是直接把s1赋值给了s2,即把s1的引用赋值给了s2,所以s2所引用的对象其实就是s1所引用的对象。所以通过==来比较时,返回true。既然它们引用的都是同一个对象,那么通过equals()方法来比较时,肯定也返回true,这里equals()方法其实在对同一个对象进行比较,自己肯定等于自己咯。
3、//////////////////////////////////////////////////////////////////////////////
string s1 = hello;
string s2 = hello;
system.out.println(s1 == s2);
system.out.println(s1.equals(s2));
以上代码段的打印结果是:
true
true
        为什么这个结果?那么来分析一下。首先这两个string对象都是作为一个基本类型来使用的,而不是通过new关键字来创建的,因此虚拟机不会为这两个string对象分配新的内存堆,而是到string缓冲池中来寻找。
        首先为s1寻找string缓冲池内是否有与hello相同值的string对象存在,此时string缓冲池内是空的,没有相同值的string对象存在,所以虚拟机会在string缓冲池内创建此string对象,其动作就是new string(hello);。然后把此string对象的引用赋值给s1。
        接着为s2寻找string缓冲池内是否有与hello相同值的string对象存在,此时虚拟机找到了一个与其相同值的string对象,这个string对象其实就是为s1所创建的string对象。既然找到了一个相同值的对象,那么虚拟机就不在为此创建一个新的string对象,而是直接把存在的string对象的引用赋值给s2。
        这里既然s1和s2所引用的是同一个string对象,即自己等于自己,所以以上两种比较方法都返回ture。
        到这里,对string对象的基本概念应该都已经理解了。现在我来小结一下:
针对string作为一个基本类型来使用:
1。如果string作为一个基本类型来使用,那么我们视此string对象是string缓冲池所拥有的。
2。如果string作为一个基本类型来使用,并且此时string缓冲池内不存在与其指定值相同的string对象,那么此时虚拟机将为此创建新的string对象,并存放在string缓冲池内。
3。如果string作为一个基本类型来使用,并且此时string缓冲池内存在与其指定值相同的string对象,那么此时虚拟机将不为此创建新的string对象,而直接返回已存在的string对象的引用。
针对string作为一个对象来使用:
1。如果string作为一个对象来使用,那么虚拟机将为此创建一个新的string对象,即为此对象分配一块新的内存堆,并且它并不是string缓冲池所拥有的,即它是独立的。
理解了以上内容后,请看以下代码段:
4、/////////////////////////////////////////////////////////////////////////////
string s1 = hello;
string s2 = new string(hello);
system.out.println(s1 == s2);
system.out.println(s1.equals(s2));
以上代码段的打印结果是:
false
true
        根据上面的小结来进行分析。第一行是把string作为一个基本类型来使用的,因此s1所引用的对象是属于string缓冲池内的。并且此时string缓冲池内并没有与其值相同的string对象存在,因此虚拟机会为此创建一个新的string对象,即new string(hello);。第二行是把string作为一个对象来使用的,因此s2所引用的对象不属于string缓冲池内的,即它是独立的。通过new关键字,虚拟机会为此创建一个新的string对象,即为它分配了一块新的内存堆。因此==比较后的结果是false,因为s1和s2所引用的并不是同一个对象,它们是独立存在的。而equals()方法所返回的是true,因为这两个对象所封装的字符串内容是完全相同的。
        现在,相信大家已经完全搞清楚string对象是怎么一回事了:)但是到此并没有结束,因为string对象还有更深层次的应用。
        这里我将分析一下string对象的intern()方法的应用:
intern()方法将返回一个字符串对象的规范表示法,即一个同该字符串内容相同的字符串,但是来自于唯一字符串的string缓冲池。这听起来有点拗口,其实它的机制有如以下代码段:
string s = new string(hello);
s = s.intern();
以上代码段的功能实现可以简单的看成如下代码段:
string s = hello;
        你一定又开始疑惑了?那么你可以先看第二个代码段。第二个代码段的意思就是从string缓冲池内取出一个与其值相同的string对象的引用赋值给s。如果string缓冲池内没有与其相同值的string对象存在,则在其内为此创建一个新的string对象。那么第一段代码的意思又是什么呢?我们知道通过new关键字所创建出的对象,虚拟机会为它分配一块新的内存堆。如果平凡地创建相同内容的对象,虚拟机同样会为此分配许多新的内存堆,虽然它们的内容是完全相同的。拿string对象来说,如果连续创建10个相同内容的string对象(new string(hello)),那么虚拟机将为此分配10块独立的内存堆。假设所创建的string对象的字符串内容十分大,假设一个stirng对象封装了1m大小的字符串内容,那么如果我们创建10个此相同string对象的话,我们将会毫无意义的浪费9m的内存空间。我们知道string是final类,它所封装的是字符串常量,因此string对象在创建后其内部(字符串)值不能改变,也因此string对象可以被共享。所以对于刚才提到的假设,我们所创建的10个相同内容的string对象,其实我们只需为此创建一个string对象,然后被其它string变量所共享。要实现这种机制,唯一的、简单的方法就是使用string缓冲池,因为string缓冲池内不会存在相同内容的string对象。而intern()方法就是使用这种机制的途径。在一个已实例化的string对象上调用intern()方法后,虚拟机会在string缓冲池内寻找与此stirng对象所封装的字符串内容相同值的string对象,然后把引用赋值给引用原来的那个string对象的string类型变量。如果string缓冲池内没有与此string对象所封装的字符串内容相同值的string对象存在,那么虚拟机会为此创建一个新的string对象,并把其引用赋值给引用原来的那个string对象的string类型变量。这样就达到了共享同一个string对象的目的,而原先那个通过new关键字所创建出的string对象将被抛弃并被垃圾回收器回收掉。这样不但降低了内存的使用消耗,提高了性能,而且在string对象的比较上也同样更方便了,因为相同的string对象将被共享,所以要判断两个string对象是否相同,则只需要使用==来比较,而无需再使用equals()方法来比较,这样不但使用起来更方便,而且也提高了性能,因为string对象的equals()方法将会对字符串内容拆解,然后逐个进行比较,如果字符串内容十分大的话,那么这个比较动作则大大降低了性能。
        说到此,大家可能对具体应用还有点模糊,那么我来举个简单的示例,以便阐述以上概念:
        假设有一个类,它有一个记录消息的方法,这个方法记录用户传来的消息(假设消息内容可能较大,并且重复率较高),并且把消息按接收顺序记录在一个列表中。我想有些朋友会这样设计:
import java.util.*;
public class messages {
arraylist messages = new arraylist();
public void record(string msg) {
messages.add(msg);
}
public list getmessages() {
return messages;
}
}
        这种设计方案好吗?假设我们重复的发送给record()方法同一个消息(消息来自不同的用户,所以可以视每个消息为一个new string(...)),并且消息内容较大,那么这个设计将会大大浪费内存空间,因为消息列表中记录的都是新创建的、独立的string对象,虽然它们的内容都相同。那么怎么样可以对其进行优化呢,其实很简单,请看如下优化后的示例:
import java.util.*;
public class messages {
arraylist messages = new arraylist();
public void record(string msg) {
messages.add(msg.intern());
}
public list getmessages() {
return messages;
}
}
        正如你所看到的,原先record()方法中的messages.add(msg);代码段变成了messages.add(msg.intern());,仅仅对msg参数调用了intern()方法,这样将对重复的消息进行共享机制,从而降低了内存消耗,提高了性能。
这个例子的确有点牵强,但是这里只是为了阐述以上概念!
至此,string对象的迷雾都被消除了,大家只要牢记这些概念,以后再复杂的string应用都可以建立在此基础上来进行分析。
更多string使用equals方法和==分别比较的是什么。
其它类似信息

推荐信息