为了账号安全,请及时绑定邮箱和手机立即绑定

Java 字符串常量池

标签:
Java

在 JDK 1.7 之前,HotSpot 虚拟机中的字符串常量池都在方法区中,用永生代实现。JDK 1.7 及以后的版本,字符串常量池移到了堆里。

JDK 1.6 的 String.intern 方法会将首次遇到的 String 对象复制到永久代,并返回这个对象的引用。

JDK 1.7 的 String.intern 方法不再复制,而是记录首次出现的 String 对象的引用。

以下用 JDK 1.8 实验探究字符串常量池。

// test1

String s1 = "red";

String s2 = "red";

System.out.println(s1 == s2); // true


// test2

String s3 = new String("red");

String s4 = new String("red");

System.out.println(s3 == s4); // false


// test3

System.out.println(s1 == s3); // false


// test4

System.out.println(s3.intern() == s1); // true

System.out.println(s3.intern() == s3); // false

System.out.println(s3.intern() == s4); // false


// test5

String s5 = new String("thunder");

String s6 = s5.intern();

String s7 = "thunder";

System.out.println(s5 == s6); // false

System.out.println(s6 == s7); // true


// test6

String s8 = new String("1") + new String("1");

// String s8 = new StringBuilder().append().toString()

String s9 = s8.intern();

String s10 = "11";

System.out.println(s8 == s9); // true

System.out.println(s9 == s10); // true

常量池可以看作是一个集合,没有重复的元素。用双引号创建的对象直接放到常量池,new 一定会在堆中创建一个新的对象,如果常量池没有值相同的对象那么会在常量池也创建一个对象。intern 的作用是判断常量池是否包含值相同的字符串,是则返回这个字符串对象的引用,否则将当前实例的引用放到常量池并返回当前实例的引用。

另外,字符串的拼接实际上是用了 StringBuilder,所以字符串 s8 的创建会伴随以下对象的创建:

  • 堆中两个不同的 String 对象 1

  • 字符串常量池中一个 String 对象 1

  • 一个 StringBuilder 对象

  • 堆中的 String 对象 11

由于 s8 的创建方式不是 new String 而是拼接,所以不会在常量池中创建值为“11”的对象,这也是 test5 和 test6 要对比的问题。


作者:FhToday
链接:https://juejin.cn/post/6989609445785337870
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。



点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消