java中String.intern的坑

空闲时间,一个好友发过来一段代码很有意思,运行的结果比较诡异,代码很简单,三两行,详细如下:

StringBuilder sb = new StringBuilder();
String str = sb.append("a").toString();
System.out.println(str.intern() == str);

执行代码,输出结果为false,还可以接受,不过再换下面这段代码

StringBuilder sb = new StringBuilder();
String str = sb.append("a").append("b").toString();
System.out.println(str.intern() == str);

执行代码,输出结果为true。这就诡异了,为什么只是多调用了一个StringBuilder.append,返回结果竟然不一样呢?

翻看了下StringBuilder.append的源码,没什么特殊的地方,没有什么对象引用的处理呀。那么真相只有一个,就是String.intern导致的了,借用柯南的一句名言:抛开所有不可能的,剩下的,不管多么匪夷所思,那都是事实。

查了下String.intern的文章,有一篇写的非常好,原文如下:https://blog.csdn.net/SEU_Calvin/article/details/52291082

读了这篇文章后,这个问题就比较合理了。

原来,jdk1.7后String.intern做了一些优化处理,拿第一个例子来说,String str = sb.append("a").toString();

这个时候,常量池里存在一个字符串"a"对象,而堆上也存在一个"a"对象str,这里str.intern返回的是常量池的对象,和堆上的str引用不同,返回false,可以解释。

再看上面的诡异的第二个例子 String str = sb.append("a").append("b").toString();这个时候,常量池存在的是"a"对象和"b"对象,但是不存在字符串"ab"对象,堆上存在值为"ab"的str对象。这时候调用str.intern,在jdk1.7之后,常量池里的"ab"对象存的是堆上"ab"字符串的引用,所以str.intern和str其实是一个引用了,==相比返回的true。

这个问题咋看还是很诡异的,String.intern也一直是个比较诡异的方法,感兴趣的可以了解一下,不要在工作中这么比较哈。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值