String的内存分配在JVM两个区域中,堆和常量池
intern()方法:常量池没有该字符串则在常量池创建该字符串对堆中的引用,并返回常量池地址。常量池存在该字符串则直接返回该常量池地址
String s1 = new String("a"); // 堆 a 常量池 a
s1.intern(); // 常量池已存在a,没有进行操作
String s2 = "a"; // 指向常量池的 a
System.out.println(s1 == s2); // false 指向常量池的s2与指向堆中的s1比较
String s1 = new String("a") + new String("b"); // 堆 a、b、ab 常量池 a b
s1.intern(); // 在常量池创建堆中ab的引用
String s2 = "ab"; // 返回的是常量池中对堆中s1的引用
System.out.println(s1 == s2); // true 指向堆中的s1和指向常量池中对堆中的引用的s2
String s1 = new String("b"); // 堆 b 常量池 b
String s2 = "b"; // 常量池 b
s1.intern(); // 常量池已存在b,没有进行操作
System.out.println(s1 == s2); // false 指向堆中的s1和指向常量池的s2进行比较
String s1 = new String("b") + new String("b"); // 堆 b、b、bb 常量池 b、b
String s2 = "bb"; // 指向常量池 bb
s1.intern(); // 常量池已存在bb,没有进行操作
System.out.println(s1 == s2); // false 指向堆中的s1和指向常量池的s1比较
总结:使用new String,堆和常量池都创建相同的字符串,使用intern,如果常量池中没有,在常量池中创建对堆中的引用
那么下面这个呢
String s = new String("abc");
String s1 = "abc";
String s2 = new String("abc");
System.out.println(s == s1);
System.out.println(s == s2);
System.out.println(s == s1.intern());
System.out.println(s == s2.intern());
System.out.println(s1 == s2.intern());
System.out.println(s.intern() == s2.intern());