Java中String.intern()方法浅记

Java中String.intern()方法浅记

String在Java中是一个比较特殊的存在。String既可以使用字面量进行赋值,也可以使用new进行赋值。

  • 使用字面量进行赋值,会直接放进字符串常量池
  • 如果使用new进行创建对象,会在堆中生辰给一个对象,也会在常量池中存放一份,两者并不相同。

注意:

字符串常量池从jdk7开始,从方法区移到了堆中。静态变量也从方法区中移到了堆中。

概念

使用intern()方法,会先判断字符串常量池中是否已经包含当前的字符串,如果没有的话,则会在字符串常量池中存放一份。在具体的实现中稍有不同。

  • 在jdk6之前(包含jdk6),字符串常量池在方法区中,与堆不在同一个区域,所以字符串常量池中是拷贝了一份字符串的对象,Java堆中的String对象和字符串常量池的String对象不是同一个。
  • 在jdk7之后(包含jdk7),字符串常量池转移到了堆中。当堆中有一个String对象的时候,在调用intern方法时,如果字符串常量池没有这个字符串,则会存放堆中String对象的地址引用,不会像jdk7之前的拷贝一份到字符串常量池中。此时,字符串常量池翠芳的和堆中String对象代表的是一个。

如果有描述不清处的欢迎大家查看《深入了解java虚拟机的》第三版的63页。字符串常量池的迁移查看46页。

代码验证

**环境:**jdk1.8

主要验证的是jdk8,也就是字符串常量池迁移到堆的情况,jdk6之前的情况,感兴趣的可以自己尝试。

测试方法:

第一种情况:

测试结果:

分析:

在new的时候会在堆中有一个,在字符串常量池中有一个。所以intern方法相当于没有起作用,因为因为字符串常量池中已经有一个相同值的对象

第二种情况:

测试结果:

分析:

由于两个new字符串的拼接,所以在字符串长量池中不会有aabb,下面的intern方法会将堆中的aabb的引用存放在字符串常量池中。这样str3和str4就相同了。

反思:

实际中使用的StringBuilder产生的字符串不在字符串常量池中的多,下面这段代码可以在《深入了解Java虚拟》63页找到。

特例:

在《深入了解Java虚拟》63页提到了一个特例,就是java这个字符串,使用下面的方式得到的是false,原因是在项目启动的时候默认会加载一个java字符串在字符串常量池。

疑惑:待解决

发现测试单元中的10, 11, 12是特例,大家可以试试。初步猜测和上面 “java” 字符串一样,在使用测试单元的,会提前加载10, 11, 12这三个字符串在字符串常量池。

测试方法代码如下:

文章知识点与官方知识档案匹配,可进一步学习相关知识Java技能树首页概览91719 人正在系统学习中

来源:凯先生boy

声明:本站部分文章及图片转载于互联网,内容版权归原作者所有,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!

上一篇 2022年5月2日
下一篇 2022年5月2日

相关推荐