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对象的创建做具体的分析:
String s1 = new String("Hello");
String s2 = new String("Hello");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
以上代码段的打印结果是:
false
true
这个原因很好解释:s1 、s2分别new了两个值为“Hello”的对象,new关键字为创建的每个对象分配一块新的、独立的内存堆,即s1、s2指向的内存空间不一致。而这两个字符串的内容是一直的,所以 equal会返回true。
看下面一个例子:
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()方法其实在对同一个对象进行比较,自己肯定等于自己咯。
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作为一个基本类型来使用:
1。如果String作为一个基本类型来使用,并且此时String缓冲池内不存在与其指定值相同的String对象,那么此时虚拟机将为此创建新的String对象,并存放在String缓冲池内。
2。如果String作为一个基本类型来使用,并且此时String缓冲池内存在与其指定值相同的String对象,那么此时虚拟机将不为此创建新的String对象,而直接返回已存在的String对象的引用。