Java String intern() 解析

String 在 java 中是一个使用最频繁的类,也是占据内存最大的类,合理的优化 String 对象,可以节省宝贵的内存资源。

String#intern()

在每次赋值的时候使用,如果常量池中有相同值,就会重复使用该对象,返回对象引用,这样一开始的对象就可以被回收掉。

例子

上一段代码

String s1 = "abc";
String s2 = new String("abc");
String s3 = s2.intern();

System.out.println("1:" + (s1 == s2));
System.out.println("2:" + (s2 == s3));
System.out.println("3:" + (s1 == s3));
System.out.println("================================");
String s4 = new String("1") + new String("1");
String s5 = "11";
System.out.println("4:" + (s4 == s5));
String s6 = s4.intern();
System.out.println("5:" + (s4 == s5));
System.out.println("6:" + (s5 == s6));
System.out.println("7:" + (s4 == s6));

结果是:

1:false
2:false
3:true
================================
4:false
5:false
6:true
7:false

解析

理解这一块的核心在于这段代码运行是分为2个阶段的, 1.类加载 2.类执行

1.类加载时(注:JDK 1.7 之后,常量池合并在堆中):

  • 字符串常量:在常量池中开辟一个空间,存放字符串对象
  • 字符串变量:会把new String() 中的字符串放入常量池中

2.类运行时:在堆内存中开辟一个空间存放该对象,String 类中的 char 数组引用常量池对象,返回堆内存中的地址给变量引用。

如果调用 intern() 方法,就会去字符串常量池中查看是否有等于该对象字符串的引用,如果有,就返回返回字符串 常量池中的引用

额外注意 s4 动态生成的字符串


动态生成的字符串直接在堆上创建,字符串常量池没有,当调用 intern 方法获取引用时,则会去常量池中判断是否有相等的引用,如果有返回引用,如果没有则放入。

intern 方法 不改版本身的指针引用
,从7就可以看出,s4调用intern 后与 s6 比较,仍不相等。

总结

  • 非动态生成的字符串,在类加载时就已经将字符串对象放入常量池中,运行时视对象是常量还是变量赋值:

    • 常量:直接执行常量池
    • 变量:先指向堆开辟的new 空间,堆再指向常量池
  • 动态生成的字符串,直接在堆上创建,调用 intern 方法时,会去常量池中判断,如果有返回地址,如果没有,放入,返回。

intern 方法,如果常量池中没有匹配的字符串,就将自己放入然后返回,否则返回字符串对象在常量池中的地址。

思考

为什么相等 ?

String a =new String("abc").intern();
String b = new String("abc").intern(); 
if(a==b) { System.out.print("a==b");}

原文 

https://segmentfault.com/a/1190000022207505

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » Java String intern() 解析

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址