关于字符串池存储的是引用还是对象的争议

目前关于字符串池(字符串常量池)在内存区域的位置大家都是没有争议的,JDK1.7以后,字符串池在堆里。但是字符串池里存储的内容有2种说法:一种是JavaGuide为主的,认为字符串池里既存了引用也存了对象;另一种是以R大为主的认为字符串池存储的只是字符串对象的引用。

字符串池里既存了引用也存了对象:

String s1 = new String("abc");这句话创建了几个字符串对象?

【JVM】常量池、运行时常量池和字符串常量池

JDK1.8关于运行时常量池, 字符串常量池的要点

字符串常量池案例分析

字符串池里存的只是引用:

请别再拿“String s = new String("xyz");创建了多少个String实例”来面试了吧

Java 中new String("字面量") 中 "字面量" 是何时进入字符串常量池的?

java基础:String — 字符串常量池与intern(二)

Java中几种常量池的区分

运行时常量池和字符串常量池的区别

class常量池、字符串常量池和运行时常量池的区别

关于字符串池与常量池

但是不论哪种观点,大家都认为语句String str = new String("abc");创建了2个对象。

只是字符串创建的位置不同:

  1. 一个在字符串池里,另一个在堆里
  2. 两个都在堆里

大家用来佐证的方法都用到了String.intern()方法:

String s1 = new String("计算机") + new String("技术");
s1.intern();
String s2 = "计算机技术";
System.out.println(s1 == s2);//true

我们来看一下不同观点关于该方法的解释。

字符串池里既存了引用也存了对象:

如果字符串常量池中已经包含一个等于此String对象内容的字符串,则返回常量池中该字符串的引用;如果没有,JDK1.7之前(不包含1.7)的处理方式是在常量池中创建与此String内容相同的字符串,并返回常量池中创建的字符串的引用,JDK1.7以及之后,字符串常量池被从方法区拿到了堆中,JVM不会在常量池中创建该对象,而是将堆中这个对象的引用直接放到常量池中,减少不必要的内存开销。(JavaGuide)

字符串池里存的只是引用:

  1. intern方法是Native调用,它的作用是在方法区中的常量池里寻找等值的对象,如果没有找到则在常量池中存放当前字符串的引用并返回该引用,否则直接返回常量池中已存在的String对象引用。
  2. a.intern()会在字符串池中查找是否有一个字符串引用所指向的对象的值等于a的值,如果有就直接返回池中的引用;如果没有,就把a指向的对象的引用放入池中,在返回该引用。

接下来我们来看不同观点下,字符串在内存中的存储情况。

字符串池里既存了引用也存了对象:

String str1 = "abc"; // 在字符串池里创建字面量对象"abc"及其引用
String str2 = new String("abc"); // 在堆里创建对象"abc"
System.out.println(str1 == str2); // false

StringTable存储引用并指向字符串池里创建的对象。

字符串池里存的只是引用:

String s = new String("2"); // 在堆里创建2个对象,s指向new出来的对象
s.intern();// 在字符串池里创建引用指向堆里的字面量对象"2"
String s2 = "2";// 字符串池里已经存在字面量对象"2"的引用,不再重复创建,s2指向已经存在的引用
System.out.println(s == s2);// false,s指向堆的new出来的对象,s2指向字符串池里的对象

String s3 = new String("3") + new String("3");// 在堆里创建3个对象,s3指向拼接后的对象
s3.intern();// 在字符串池里创建引用指向堆里的字面量对象"33"
String s4 = "33";// 字符串池里已经存在字面量对象"33"的引用,不再重复创建,s4指向已经存在的引用
System.out.println(s3 == s4);// true

这里的区别在于字符串池里是否包含堆里创建字面量的区域,如果单纯的认为StringTable就是字符串池(String Pool),那么字符串池确实只有引用,否则既保存了引用也保存了对象。

实际上,字面量是否在字符串池里重复引用,已经在编译阶段的class常量池里完成了。

欢迎大家批评指正!

  • 8
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值