前置知识:
1,== 对于对象比较的是所指向的地址是否相同
2,当调用intern方法时,如果池已经包含与equals(Object)方法确定的相当于此String对象的字符串,则返回来自池的字符串。 否则,此String对象将添加到池中,也就是该字符串所在堆的地址,并返回对此String对象的引用。
3,StringBuilder 通过toString 产生的 String,并不会先在字符串常量池中先创建一份。但是new String(“abc”) 会先在字符串常量池中创建一个"abc"
String s1 = new String(“abc”) 发生了什么
首先,“abc” 将会存于字符串常量池中(1.7之后也在堆中),new 产生对象在堆中(为了区分常量池中,其实都在堆中),s1指向new 的堆区域。
String s1 = new String("abc")
// false : s1.intern()指向常量池
// s1 指向堆
System.out.println(s1==s1.intern());
String s2 = "字符串";
// true: s2指向常量池
System.out.println(s2==s2.intern());
StringBuilder 通过toString 产生的String
// 常量池中不会产生java1('ja','va1'倒是存在)
// s1.intern()在常量池中如果不存在s1对应的字符串,会将s1对应的堆地址放入字符串常量池,而不是将s1对应的字符串放入
String s1 = new StringBuilder().append("ja").append("va1").toString();
// true
System.out.println(s1.intern() == s1);
// 首先"字符串"会放入常量池,s2指向堆
String s2 = new StringBuilder("字符串").toString();
// s2.intern() 由于常量池中存在"字符串",因此指向常量池
// s2指向堆,因此为false
System.out.println(s2.intern() == s2);
// 和上边相同
System.out.println(s2 == "字符串".intern());
// 指向字符串常量池
String sa = "abc"+"bcd";
// true
System.out.println(sa==sa.intern());
本质就是看两者指向是否相同,如果s1.intern对应的值不在常量池中,就会将s1 的地址放到常量池中。