String s0 = new StringBuilder("漠").append("然").toString(); System.out.println(s0 == s0.intern());
String s1 = new StringBuilder("漠").append("然").toString(); System.out.println(s1 == s1.intern());
//true false
本渣渣研究了一天 string 相关文章,越看越懵逼。求大佬赐教。
1
lwj871731342 2019-01-20 21:35:58 +08:00
一个渣渣的猜测:
第一次调用 intern 的时候将其放入了常量池,这时候和 s0 的引用相同 第二次调用 intern 的时候找到了之前 s0 放入常量池的那个字符串的引用,这时的引用和 s1 的引用不同 没有确切研究过...期待大佬的正确回答 |
2
shalk 2019-01-20 21:38:54 +08:00
对于你这个问题,你查询以下 intern 方法的说明。
因为 intern 方法是 native 方法,所以要看底层实现有关,java 版本不同会有所不同 网上有很多文章 |
3
everwanna 2019-01-20 21:41:18 +08:00 via iPhone
判断字符串是否相等用 equal, == 只能判断引用和数值是否相等。
字符串的存储专门做了优化,相同的字符串在内存中尽量用复用,但并不保证只有一个 |
4
zsh1995 2019-01-20 21:41:41 +08:00
调用 intern 时,如果在内部的 string pool 已经存在相同的 string 时,则返回 pool 中的值,否则把当前 string 放入 pool,并返回自身。
第一次调用时,"漠然"不存在,所以将它放入 string pool,s0 等于 s0.intern()。 第二次调用时,"漠然"已存在,s1.intern() 返回的是 string pool 中的值,即 s0。 |
5
BBCCBB 2019-01-20 21:42:30 +08:00
s1.intern() 返回的是 s0 的地址,而 s1 是堆里一个新的`漠然`的地址。 仅供参考
|
6
zpxshl OP @zsh1995 大哥注意一下,s0 = new StringBuilder("漠").append("然").toString(); 这时候没调用 intern 方法。 但是输出的结果证明了此时 s0 已经是 pool 里面的值。
|
7
zpxshl OP @zsh1995 我的是 jdk1.8,网上大部分文章都看了,没有合理的解释。
String sss = new StringBuilder("a").append("b").toString(); System.out.println(sss == sss.intern()); // true 个人偏向和 StringBuilder.toSting() 有关,同样是 native 方法。 难道是 StringBuilder.toString 在 string 不在 pool 时会将其加入 pool,并返回 pool 的值。在 string 已经在 pool 时,反而不返回 pool 的值? |
8
zpxshl OP @BBCCBB @everwanna @lwj871731342 @shalk @zsh1995
感谢各位大佬回复。已经找到答案。 jdk1.7 后:string pool 存的是 string 的引用(而非 string 本身)。intern 返回的是该 string 对象第一次出现的位置(在 Heap 中)。 实在惭愧,研究了一天没想到答案,一来 v 站问就很快知道了。。。 |
9
zhuawadao 2019-01-21 09:22:55 +08:00
我查了 1.8 的 API:
当调用 intern 方法时,如果池已经包含与 equals(Object)方法确定的相当于此 String 对象的字符串,则返回来自池的字符串。 否则,此 String 对象将添加到池中,并返回对此 String 对象的引用。 这就是答案吧 |
10
payboy 2019-01-21 17:14:54 +08:00 1
String s0 = new StringBuilder("漠").append("然").toString();//s0 指向堆中引用“漠然”
s0.intern();//java7:因常量池不存在“漠然”字符串对象,存储堆中“漠然”的引用并返回 String s1 = new StringBuilder("漠").append("然").toString();//s1 指向堆中引用“漠然”,与 s0 指向引用不是同一个 s1.intern();//java7:因常量池已存在“漠然”字符串对象引用,返回引用,与 s0 指向引用是同一个 |