首页 新闻 会员 周边 捐助

关于Java String的intern()方法

0
悬赏园豆:10 [已解决问题] 解决于 2019-02-26 18:35
        String s1="abc",s2=new String("abc");
        s2.intern();
        System.out.println(s1==s2);

在 jdk10 的环境下,我知道s2的引用指向的是堆,我想问s1指向的哪个区域呢?常量区吗?如果是常量区,这个常量区是位于堆里的吗?
在这个上下文中,s2.intern();的作用是什么呢?是在常量区加入了指向s2的引用吗?

darknessplus的主页 darknessplus | 初学一级 | 园豆:141
提问于:2019-02-25 22:04
< >
分享
最佳答案
0

很久前研究过这个问题,看深入理解jvm的时候有关于intern的讨论,当时是说intern方法在jdk6和jdk7之间会有不同。
常量池一般是类加载的时候确定了一些自定义的常量,比如s1="abc"。但是intern方法可以让方法在运行时也可以往常量池中添加常量。
intern方法大致理解为:
如果常量池中存在当前字符串, 就会直接返回当前字符串. 如果常量池中没有此字符串, 会将此字符串放入常量池中后, 再返回。
一般在jdk6和jdk7以后会有区别,是因为常量池在7以后被拿到堆中了。

收获园豆:10
让我发会呆 | 老鸟四级 |园豆:2929 | 2019-02-26 16:41
String s=new String("123");
s.intern();

jdk7以后常量池是不是也可以放引用啊?比如上面这个代码,常量池中放的是"123"这个字符串还是s这个对象的引用?

darknessplus | 园豆:141 (初学一级) | 2019-02-26 16:44

@darknessplus: 我一般是这么简单理解的,
s是存在栈中的,s地址指向堆中,就是一个String对象实例,当然也包含它的对象数据实例"123"。
String s1 = s.intern();其实就是如果在常量池中有"123"则新建的s1对象直接指向这个"123",
如果常量池没有"123",则创建出来,新建的s1对象还是直接指向这个"123"。

让我发会呆 | 园豆:2929 (老鸟四级) | 2019-02-26 17:40

@让我发会呆: 感谢!
https://blog.csdn.net/shanksqian/article/details/78330294 这个总结的也很好

darknessplus | 园豆:141 (初学一级) | 2019-02-26 18:34
其他回答(2)
0

这是个有意思的问题呀

        String s1 = "Test";
        String s2 = "Test";
        String s3 = new String("Test");
        final String s4 = s3.intern();
        assertTrue(s1 == s4);
Bluto | 园豆:317 (菜鸟二级) | 2019-02-26 09:33
0

s1指向的是常量池,常量池是位于方法区的,区别于堆,你可以了解下jvm的内存,至于String的intern()方法返回的是规范化文本,简单说就是使用equals方法与常量池中的字符串比较,看看有没有相同的字符串,如果有直接返回常量池中的引用,如果没有,则在常量池添加一个跟自己一样的字符串并返回引用

不懂java的小白 | 园豆:208 (菜鸟二级) | 2019-02-26 13:52

常量区位于方法区?jdk1.7以后不是将常量区放在堆里了吗?同时常量区还可以保存字符串在堆里的引用,这是我看过一些博客上说的。

所以我的疑问是s1指向的是方法区中的常量区,还是堆中的常量区?

还有intern方法的过程是怎么样的?既然常量区中有字符串在堆中的引用,是不是每次对比还要区分是字面量还是引用?

支持(0) 反对(0) darknessplus | 园豆:141 (初学一级) | 2019-02-26 14:08

@darknessplus: 我看的应该是jdk7之前的

支持(0) 反对(0) 不懂java的小白 | 园豆:208 (菜鸟二级) | 2019-02-27 10:46
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册