- 先来看一段代码,看的时候顺便想想答案都是什么?
package base;
public class StringDemo {
public static void main(String[] args) {
String str1 = "abc";
String str2 = "ab";
String str3 = "c";
String str4 = str2 + str3;
String str5 = str2 + str3;
String str6 = new String("abc");
String str7 = "ab" + "c";
String str8 = str2 + "c";
System.out.println(str1 == str6);
System.out.println(str1 == str4);
System.out.println(str4 == str5);
System.out.println(str1 == str7);
System.out.println(str1 == str8);
}
}
- ①
str1 == str6
:str1 采用字符串的直接赋值方式,该过程会把 “abc” 这个对象自动保存到对象池(堆上)中,因此在该题中对象池里就已经有 “abc” 这个对象了;str6 采用构造方法赋值的方式,直接在堆上开辟新空间,而且该方法不会将对象入池。因此 str1 和 str6 肯定不是同一块地址,答案为false
。
这里牵扯到String类两种对象实例化方式的区别:
Ⅰ、直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池中以供下次使用。
Ⅱ、构造方法:会开辟两块堆内存空间,其中一块成为垃圾空间,不会自动保存在对象池中,可以使用intern()
方法手工入池。
- ②
str1 == str4
:由题目可知 str4 是由 str2 和 str3 字符串拼接得到的,但是这里会将 str2 和 str3 全部转为 StringStringBuilder 而后调用其 append() 方法。因此 srt1 和 str6 地址也是不相同的,答案为false
。 - ③
str4 == str5
:② 中已经说过 str4 是由 str2 和 str3 通过 append() 来的,这里按理说,str5 也是 str2 和 str3 拼接得到的,所以按理说 str4 和 str5 应该是同一块地址,但是事实证明 str5 和 str4 地址不同(自认为是比较难理解的一个比较!),答案为false
。
- ④
str1 == str7
:刚才 str4 中两个参数的值都是字符串变量,但是该题中 str7 是由 “ab” 和 “c” 两个字符串常量拼接而来的。此时问题就来了,字符串常量在进行拼接时会像字符串变量那样先转换为 StringBuilder 再调用 append() 方法进行拼接吗?如果实在搞不清楚,不如用事实来说话,
显然字符串纯常量的拼接(“+”操作)不会转换为 StringBuilder,直接在常量池内寻找是否已经在已有值,常量池中已经有 “abc” 这个对象了,答案为true
。 - ⑤
str1 == str8
:这个题中的 str8 和 str4、str7 是差不多的,只不过就是字符串是纯字符串变量拼接形成的,还是纯字符串常量拼接形成的,或者是字符串常量和字符串变量拼接形成的而已。那么 str4 和 str7 都已经包括了前两种方式,该题则是最后一种方式的字符串拼接,根据下图得出结论,答案为false
。
通过该题总结如下:
- 在进行字符串拼接时,只有纯常量的拼接(“+”)不会转换为
StringBuilder
,而是直接在常量池内寻找是否已经在已有值。 - 否则,只要存在一个字符串变量的 “+” 操作,都会转为
StringBuilder
调用append()
方法。