BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / java / #64263同步于 2020/8/19
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖

不懂就问:String 和 intern()

crazyalltnt
2020/8/19镜像同步16 回复
根据《深入理解java虚拟机》 JDK 1.7后,intern 方法会先去查询常量池中是否有已经存在,如果存在,则返回常量池中的引用,这一点与之前没有区别。 区别在于,如果在常量池找不到对应的字符串,则不会再将字符串拷贝到常量池,而只是在常量池中生成一个对原字符串的引用。 简单的说,就是往常量池放的东西变了:原来在常量池中找不到时,复制一个副本放到常量池,1.7后则是将在堆上的地址引用复制到常量池。 那么下面这段代码: 1. 对于 s 和 s2,s.intern() 时发现 “1” 不在字符串常量池内,会把堆的引用保存到字符串常量中,那么当 String s2 = "1" 的时候,常量池中存在“1” 的引用地址,s2应该直接拿到指向s堆对象的引用,这时候判断,s==s2 应该是true ? 2. 对于s3和s4, 根据上面的说法s4拿到s3堆空间的引用所以返回true没问题 综上:为啥返回的不一样,第一个不应该是true吗?如果第一个是false,为啥第二个就是true了? 求指教,谢谢! ```java //jdk1.8 String s = new String("1"); s.intern(); String s2 = "1"; System.out.println(s == s2); //false String s3 = new String("1") + new String("1"); s3.intern(); String s4 = "11"; System.out.println(s3 == s4); //true ```
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
xxpxxxxp机器人#1 · 2020/8/19
奇怪的知识增加了
wangzhigang机器人#2 · 2020/8/19
瞅瞅字节码吧,说不定能搞清楚[ema2]
Lykr机器人#3 · 2020/8/19
https://www.cnblogs.com/gxyandwmm/p/9495923.html 讲的很清楚了
crazyalltnt机器人#4 · 2020/8/19
所以关键是第二段的"+"对吗?这一句在编译是不做运算,所以常量池没有放入11而前面的s在编译时就在常量池放入了1。[ema11] 【 在 Lykr (Lykr) 的大作中提到: 】 : https://www.cnblogs.com/gxyandwmm/p/9495923.html 讲的很清楚了
itachiwwg机器人#5 · 2020/8/19
第一个new String("1")是先后在常量区和堆上创建”1“和对象,s.intern时候 发现常量区已经有了”1“所以就不动了; 第二个 s3一开始指向的是堆中的11,但执行 intern 后,在常量区中增加了对堆中”11“的引用,定义s4是指向了该引用和s3是同一个对象,所以是true
wwj1204机器人#6 · 2020/8/19
楼上正解 【 在 itachiwwg (阿呆) 的大作中提到: 】 : 第一个new String("1")是先后在常量区和堆上创建”1“和对象,s.intern时候 发现常量区已经有了”1“所以就不动了; : 第二个 s3一开始指向的是堆中的11,但执行 intern 后,在常量区中增加了对堆中”11“的引用,定义s4是指向了该引用和s3是同一个对象,所以是true
S12344机器人#7 · 2020/8/19
https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html 看完这篇就懂了
crazyalltnt机器人#8 · 2020/8/19
对对,过程我明白了。原理方面是我在4楼说的那个吗? 就是为何s创建时常量和堆都有1而s3只有堆中有1而常量池没有。 String s3 = new String("1") + new String("1"); +是stringbuilder实现的所以在执行之前,编译后加载的时候11没有放进常量池,1被放进常量池。而String s = new String("1");在编译后加载的时候就被放进常量池? 我的理解对吗?谢谢啦! 【 在 itachiwwg (阿呆) 的大作中提到: 】 : 第一个new String("1")是先后在常量区和堆上创建”1“和对象,s.intern时候 发现常量区已经有了”1“所以就不动了; : 第二个 s3一开始指向的是堆中的11,但执行 intern 后,在常量区中增加了对堆中”11“的引用,定义s4是指向了该引用和s3是同一个对象,所以是true
crazyalltnt机器人#9 · 2020/8/19
嗯嗯,谢谢!看来主要区别原因就在于+号实现和执行,执行前,编译和加载时11没有在常量池被创建,只创建了直接new的1。 【 在 S12344 (Woo) 的大作中提到: 】 : https://tech.meituan.com/2014/03/06/in-depth-understanding-string-intern.html : 看完这篇就懂了