搞了一天的String#internal,终于想通了

前言:铁汁们,今天又是代码被虐爆肝的一天,被啥虐了嘞,看标题就知道了,话不多说上代码。

public class StringInternTest {

    public static void main(String[] args) {

        String s1 = "1";
        String s= new String("1");
        s.intern();
        System.out.println(s == s1);

        String s3 = new String("a") + new String("b");
        s3.intern();
        String s4 = "ab";
        System.out.println(s3 == s4);

    }
}

运行结果是这样:
在这里插入图片描述
起初我觉得不可思议,两串差不多的代码,运行结果却是截然相反,而且
在我的印象里,String类型的数据判断是否相等要用equals方法,定义两个String类型的变量用==号判断结果为true我还是头一次见到,真是越学越放弃。所以不懂就要问度娘:

Java为了提高性能,对基本数据类型和String类型提供了常量池的概念,相当于就是做了缓存处理了。
对于String类型数据:

  • 直接使用双引号声明出来的String对象会直接存储在常量池中。
  • 如果不是用双引号声明的对象,可用使用String的intern方法。intern方法会从字符串常量池中查询当前字符串是否存在,若不存在就会将当前字符串放入常量池中。

啥意思?
先看下s和s1
在这里插入图片描述
结果同我预想的一样,s1指向的是常量的地址,s是指向堆中的地址,二都不相等,结果为false。
再来看下s3和s4:
在这里插入图片描述
但是不对啊,我s3还是指向的堆里面的地址,s4是指向的常量池里面的地址,这不还是一样不相等吗?
纠结了很久才找到答案:

JDK7之前确实是这样,直接复制一个字符串放到常量池中,而在JDK7之后,常量池就放进堆里面一起存放了,所以不需要再复制对象而是直接添加对象的引用到常量池就可以了。

所以最终图可以这么画:
在这里插入图片描述
我是阿雷,我在秃头的路上等着你。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值