StringBuilder intern 问题


String str = new StringBuilder("lisi").toString();
System.out.println(str == str.intern());

String str2 = new StringBuilder("zhang").append("san").toString();
System.out.println(str2 == str2.intern());

为什么会一个false 一个true

首先看intern的定义:如果字符串常量池里存在一个和当前字符串对象等价的字符串对象(equals==true认为相同),那么返回字符串常量池里那个对象.如果不存在,把当前字符串对象存进常量池, 返回当前字符串对象.
再看==这里是指地址相同才为true
这里不难理解,stringbuilder在进行append操作时在转字符串会生成一个字符串常量在内存

因为字符串常量池在堆中了;
差别就在这个.append上
第一个: new StringBuilder("lisi").toString(); 首先 字符串 "lisi" 在常量池中没有,会创建一个(引用1),然后StringBuilder指向这个引用(引用2),然后.toString()生成一个新的字符串指向的是StringBuilder(引用3);str == str.intern() 就是 引用3 == 引用1,所以 false;
第二个:new StringBuilder("zhang").append("san") ,字符串 "zhang"、"san" 一开始在常量池中都是没有的,会创建2个(引用1,引用2),这个时候是还没有创建"zhangsan" 这个字符串的;StringBuilder 自己的引用是引用3,.toString() 生成一个新的字符串 (引用4),引用4的这个字符串"zhangsan" 才会算在常量池里面,str2 == str2.intern() 就是 引用4 == 引用4 ,所以是true;包括后续如果有 "zhangsan" 这个字符串,它与str2 用 == 判断也会是true。
在你的这代码基础上再增加下面的代码,任然会是true

String a = "zhangsan";
        System.out.println(a == str2);

img