关于String常量池和String对象的测试和总结

基本操作

1.String s = “a”;

堆中:创建String(“a”)对象
常量池(StringTable): "a"字面量引用 -> 堆中String(“a”)对象

2.String s = “a” + “a”;

堆中:String(“aa”)对象
常量池: "aa"字面量 -> 堆中String(“aa”)对象

注意:“a” + "a"编译时被合为"aa"字面量,也就是没有存在"a"字面量,所以"a"没有加入常量池

3.String s = new String(“a”);

堆中:
1.s引用 -> String(“a”)对象
2."a"字面量 -> String(“a”)对象

常量池: "a"字面量 ->堆中("a"字面量 -> String(“a”)对象)

4.String s = new String(“a”) + “a”;

堆中:
1.s引用 -> String(“aa”)对象
2."a"字面量 -> String(“a”)对象

常量池: "a"字面量 ->堆中("a"字面量 -> String(“a”)对象)

注意:s引用指向的String(“aa”)对象,因为是new出来的,也就是没有存在"aa"字面量,所以没有加入常量池

复合判断

1.

String s = "a";
s.intern();

堆中:s引用 -> String(“a”)对象
常量池: "a"字面量 -> (s引用 -> 堆中String(“a”)对象)

注意: 常量池中已有"a"字面量,s.intern()不会在常量池再放"a"字面量了

2.

String s = new String("a");
s.intern();

堆中:
1.s引用 -> String(“a”)对象
2."a"字面量 -> String(“a”)对象

常量池: "a"字面量 -> 堆中("a"字面量 -> String(“a”)对象)

注意: 常量池中已有"a"字面量,s.intern()不会在常量池再放"a"字面量了

3.

String s = new String("a") + "a";
s.intern();

堆中:
1.s引用 -> String(“aa”)对象
2."a"字面量 -> String(“a”)对象

常量池:
1."aa"字面量 -> (s引用 -> String(“aa”)对象)
2."a"字面量 -> 堆中("a"字面量 -> String(“a”)对象)

注意:第一句new String时常量池没有"aa"字面量,第二句s.intern()将"aa"字面量添加进常量池

4.

String s = new String("a") + "a";
String s1 = "aa";
System.out.println(s == s1);		//false

堆中:
1.s引用 -> String(“aa”)对象
2."a"字面量 -> String(“a”)对象
3.s1引用 -> String(“aa”)对象

常量池:
1."aa"字面量 -> (s1引用 -> String(“aa”)对象)
2."a"字面量 -> 堆中("a"字面量 -> String(“a”)对象)

注意: 第一句new String并没有将"aa"添加到常量池,第二句中出现了字面量"aa",此时s1指向堆中新创建的一个String(“aa”),并且该字面量会添加到常量池

5.

String s = new String("a") + "a";
s.intern();
String s1 = "aa";
System.out.println(s == s1);		//true

堆中:
1.s引用 -> String(“aa”)对象
2."a"字面量 -> String(“a”)对象

常量池:
1."aa"字面量 -> (s引用 ->堆中String(“aa”)对象)
2."a"字面量 -> 堆中("a"字面量 -> String(“a”)对象)

注意:第二句s.intern()会将s引用的String(“aa”)添加到常量池中,所以第三句"aa"字面量看到常量池中已有"aa",就将s引用的String(“aa”)赋值给s1

6.

String s = new String("a") + "a";
String s1 = "aa";
System.out.println(s == s1);				//false
System.out.println(s.intern() == s);		//false
System.out.println(s.intern() == s1);		//true

堆中:
1.s引用 -> String(“aa”)对象
2."a"字面量 -> String(“a”)对象
3.s1引用 -> String(“aa”)对象

常量池:
1."aa"字面量 -> (s1引用 -> String(“aa”)对象)
2."a"字面量 -> 堆中("a"字面量 -> String(“a”)对象)

注意:第二句"aa"字面量会在创建String(“aa”)对象,赋值给s1,并且会将"aa"字面量加到常量池中。s.intern()会检测常量池中是否有"aa",如果没有就放入s引用,有的话直接返回常量池中"aa"引用的对象,而常量池中的“aa”放的是s1,所以s.intern() = s1

总结

关于字符串的几种情况总结下:

字符串常量池
字面量(用""包起来的串值)常量池没有的话就new常量池中有该字面量,就不用放入了。

没有的话就在堆中new一个,并在常量池里引用到堆中new的String对象
new String(“a”)new一个String对象new String(“a”)创建的String对象不会放入常量池,但是"a"是字面量。

只要出现字面量要按上面字面量来处理
“a” + “a”常量池没有的话会new String(“aa”)“a” + “a"编译时会合并为"aa”,按"aa"字面量处理
new String(“a”) + “a”new + 字面量,底层是用StringBuilder的append方法,最后会new String(“aa”)

过程当中没有出现"aa"字面量。

常量池没有"a"的话会new String(“a”)
只会处理"a"字面量
new String(“a”) + new String(“a”)同上,底层是用StringBuilder的append方法,最后会new String(“aa”) 。

常量池没有"a"的话会new String(“a”)
只会处理"a"字面量
s.intern()不处理常量池中没有s的字面量,就把s字面量加到常量池,且常量池中字面量指向s。

如果常量池已经有s的字面量,则返回常量池中字面量指向的堆中的String对象

版权声明:本文为fengyuyeguirenenen原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。