首先大家知道,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。
下面开始代码讲解
(1)
String str3 = new String("nihao");
String str4 = new String("nihao");
System.out.println(str3==str4);
System.out.println(str3==str4);
以上代码的打印结果为
false
true
因为str3和str4都是通过New 关键字来创建的,因此两个字符串在堆中分别会分配一块内存空间来存放这两个字符串。所以两个字符串虽然指向的对象内容相同,但是存放的两个对象的首地址不同。所以我们可以推断出,str3==str4返回的是false,而str3.euqals(str4)判断的是两个引用指向的对象的内容,不包括比较两个对象的引用。所以,我们可以推出返回结果是true。
(2)
String str5 = new String("nihao");
String str6 = str5;
System.out.println(str5==str6);
System.out.println(str5.equals(str6));
以上代码的打印结果为
true
true
因为str5的引用又赋值给了str6,所以此时str5存放的首地址和str6存放的首地址相等。那么引用的对象值也是相等的。两个返回的都是true。
(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。
(4)
String str1 = "nihao";
String str2 = new String("nihao");
System.out.println(str1==str2);
System.out.println(str1.equals(str2));
以上代码段的打印结果是:false
true
这个也很好理解,str1和str2一个是作为字符串类型创建,一个作为对象创建,两者相比较,如果是“==”判断相等,那么比较的是引用和引用对象的内容。所以返回的是false。、
而str1.equals(str2)比较的是内容。内容是一样的,所以返回true。