彻底搞懂String.intern()
目录
小案例
|
|
直接给出结果
jdk6: false;false
jdk7及以后: false;true
分析
定义:如果字符串常量池中存在值和调用者值相同则返回常量池中那个值的引用。如果不存在则将调用者的 object 放入字符串常量池并返回引用。
注意这个object,这是关键所在,但是英文定义没有展开。
jdk7之前如果不存在值与调用者值相同则将该值放入字符串常量池,jdk7及以后版本出于性能考虑将调用者的引用地址放入字符串常量池,这就是小案例中结果不同的根本原因。
也就是说字符串常量池在7以后不再只存放值,也有可能是引用,之后的操作都不会改变里面的情况。
再来探讨一下字符串常量池中什么时候放入值或者引用,比如上题为什么要手动s1.intern()
,new String("a") + new String("b")
不会将ab放入常量池吗?
下面从字节码的角度分析test2过程:
结论
-
只在常量池上创建对象
-
只在堆上创建对象
-
在堆上创建对象,在常量池上创建常量
因为先对字面量a执行ldc,再new String, 可以查看字节码
1 2 3 4 5 6
0 new #7 <java/lang/String> 3 dup 4 ldc #8 <a> 6 invokespecial #9 <java/lang/String.<init>> 9 pop 10 return
-
在堆上创建对象,在常量池上创建引用
有了上面结论下面的案例就很好解决了:
|
|
分别执行t1、t2
jdk版本 | 方法 | 结果 | 说明 |
---|---|---|---|
6 | t1 | false;true | 常量池中存放ab |
7 | t1 | true;true | 常量池中存放ab引用 |
7 | t2 | false;true | 常量池中存放ab |