位置
StringTable
- jdk1.6在方法区常量池中。
- jdk1.8在堆中。
原则
-
编译期在StringTable,运行期在Heap。
-
使用""修饰的字符,编译期间存储到StringTable中,当再次用 ""创建的时候,会首先从常量池中去获取。
-
使用构造器new String("")创建的对象会在运行期存储到heap。
-
使用包含变量的字符串连接符如"aa" + s1创建的对象是运行期才创建的,存储在heap中。
“aa” + s1操作实际上是编译器创建了StringBuilder对象进行了append操作后通过toString()返回了一个字符串对象。
intern()
- jdk1.8 将这个字符串对象尝试放入串池,如果有则不会放入。如果没有则会放入串池,会把串池中的对象返回。
- jdk1.8前 将这个字符串对象尝试放入串池,如果有则不会放入。如果没有则会把此对象复制一份放入串池(即副本,副本和本身不同,是2个对象),会把串池中的对象返回。
练习
创建了几个对象?
String s = new String("abc");
2个。一个在堆中,一个在字符串常量池中。
String s1 = new String("abc");
String s2 = new String("abc");
3个。字符串常量池只会保存一份内容相同的字符串。两个在堆中,一个在字符串常量池中。
String s = "abc";
1个。在字符串常量池中。
String str1 = new String("A"+"B");
4个。字符串常量池3个(“A”,“B”,“AB”),堆1个(new String(“A”+“B”)),
判断输出
String str1 = "AB";
String str2 = "A";
String str3 = "B";
String str4 = "A" + "B";
String str5 = str2 + str3;
System.out.println(str1 == str4); //true
System.out.println(str1 == str5); // false
第4行只是字符串的拼接。
String str1 = "a";
String str2 = "b";
String str3 = "ab";
String str4 = str1 + str2;
String str5 = new String("ab");
System.out.println(str5.equals(str3)); //true
System.out.println(str5 == str3); //false
System.out.println(str5.intern() == str3); //true
System.out.println(str5.intern() == str4); //false