我们首先来了解几个知识点
- 直接赋值
我们定义一个String
类型然后将字符串abc
直接赋值给它,此时在jvm层面就会使用到一个字符串常量池,会将字符串abc
放入常量池中,然后返回指向常量池中的引用(如果常量池中已经存在了相同的字符串,就直接返回存在的引用)。
String str = "abc";
- 使用
new
关键字创建对象
(1)当时用到new
关键字进行对象创建时,jvm会在堆中给这个对象分配一块内存。
(2)判断字符串常量池中是否已经存在了这个字符串,如果不存在,也会将这个字符串放入常量池中,如果存在则不做任何处理。
(3)返回在堆内存中的引用。
String str = new String("def");
- 字符串相加
编译时拼接:如果拼接的字符串是编译时常量(即都是字面量),拼接结果会直接放入常量池中。
运行时拼接:如果拼接的字符串包含变量或是新创建的字符串对象,拼接会在运行时进行,通常会在堆中创建新的字符串对象。String str = "a" + "b";
String a = "a"; String b = "a"; String ab = a + b; String str = new String("a") + new String("b");
了解了这几个知识点,那么我们来分析一下以下情况
String str1 = "a";
String str2 = "b";
String str3 = "a" + "b";
String str4 = "ab";
String str5 = new String("a") + new String("b");
System.out.println(str1 + str2 == str3); // false
System.out.println(str3 == str4); // true
System.out.println(str1 + str2 == str4); // false
System.out.println(str3 == str5); // false
System.out.println(str4 == str5); // false
str1 + str2 == str3 // false
由于str1
和str2
是变量,变量的拼接会在运行时进行,会创建一个新的对象(堆中),而str3
是两个字面量进行拼接,会先放入常量池(方法区中),然后返回常量池中的引用,所以这两个肯定是不相等的,结果就是false
。
str3 == str4 // true
由于str3
会在编译时进行拼接,然后将拼接好的字符串放入常量池中,所以常量池中已经有了字符串"ab"
,str4
就会直接返回常量池中的引用了。
str1 + str2 == str4 // false
这个和第一种情况相同,str4
和str3
都是指向的常量池中的同一个字符串,所以也是false
。
str3 == str5 // false
str3
是指向的常量池中的字符串,而str5
是两个新创建的字符串对象相加,会创建一个新的对象放入堆中,所以也是false
。
str4 == str5 // false
和上一种情况相同,一个指向常量池中的字符串,一个指向堆中的对象,结果也是false
。