字符串-详解 String.intern() 方法
创作时间:
作者:
@小白创作中心
字符串-详解 String.intern() 方法
引用
CSDN
1.
https://blog.csdn.net/weixin_45628042/article/details/140118627
String的intern()方法是Java中一个非常重要但又容易被误解的概念。它涉及到字符串常量池的管理机制,对于理解Java内存管理和优化字符串处理至关重要。本文将通过详细的解释和代码示例,帮助读者全面理解intern()方法的工作原理及其在不同Java版本中的变化。
理解:当你调用一个字符串的 intern() 方法时,JVM会检查字符串常量池中是否已存在该字符串的副本
如果存在:该方法将返回字符串常量池中该字符串的引用,而不是你原本持有的那个字符串对象的引用。即使你原本是通过 new String(…) 创建的对象,调用 intern() 后你得到的将是一个指向字符串常量池中该字符串的引用。
如果不存在:JVM会将该字符串添加到字符串常量池中,并返回字符串常量池中该字符串的引用。
使用双引号声明的字符串对象会保存在字符串常量池中
使用 new 关键字创建的字符串对象会先从字符串常量池中找,如果没找到就创建一个,然后再在堆中创建字符串对象;如果找到了,就直接在堆中创建字符串对象。(在Java中,字符串常量池是一个特殊的存储区域,它用来存储唯一的字符串常量。当你使用字符串字面量(即直接写在代码中的字符串,如"hello")时,JVM会首先检查字符串常量池中是否已经存在该字符串。如果存在,就返回常量池中该字符串的引用;如果不存在,就将其添加到常量池中,并返回新添加的字符串的引用。)
针对没有使用双引号声明的字符串对象来说,就像下面代码中的 s1 那样:
String s1 = new String("二哥") + new String("三妹");
如果想把 s1 的内容也放入字符串常量池的话,可以调用 intern() 方法来完成。
不过,需要注意的是,Java 7 的时候,字符串常量池从永久代中移动到了堆中,
虽然此时永久代还没有完全被移除。Java 8 的时候,永久代被彻底移除。
这个变化也直接影响了 String.intern() 方法在执行时的策略,
Java 7 之前,执行 String.intern() 方法的时候,不管对象在堆中是否已经创建,
字符串常量池中仍然会创建一个内容完全相同的新对象;
Java 7 之后呢,由于字符串常量池放在了堆中,
执行 String.intern() 方法的时候,如果对象在堆中已经创建了,
字符串常量池中就不需要再创建新的对象了,而是直接保存堆中对象的引用,也就节省了一部分的内存空间。
String s1 = new String("二哥三妹");
String s2 = s1.intern();
System.out.println(s1 == s2);
//false
第一行代码,字符串常量池中会先创建一个“二哥三妹”的对象,然后堆中会再创建一个“二哥三妹”的对象,s1 引用的是堆中的对象。
第二行代码,对 s1 执行 intern() 方法,该方法会从字符串常量池中查找“二哥三妹”这个字符串是否存在,此时是存在的,所以 s2 引用的是字符串常量池中的对象。
也就意味着 s1 和 s2 的引用地址是不同的,一个来自堆,一个来自字符串常量池,所以输出的结果为 false。

String s1 = new String("二哥") + new String("三妹");
String s2 = s1.intern();
System.out.println(s1 == s2);
//true
第一行代码,会在字符串常量池中创建两个对象,一个是“二哥”,一个是“三妹”,然后在堆中会创建两个匿名对象“二哥”和“三妹”,最后还有一个“二哥三妹”的对象,s1 引用的是堆中“二哥三妹”这个对象。
第二行代码,对 s1 执行 intern() 方法,该方法会从字符串常量池中查找“二哥三妹”这个对象是否存在,此时不存在的,但堆中已经存在了,所以字符串常量池中保存的是堆中这个“二哥三妹”对象的引用,也就是说,s2 和 s1 的引用地址是相同的,所以输出的结果为 true。
String s1 = new String(“二哥”) + new String(“三妹”)等价于下面步骤:
- 创建一个 StringBuilder 对象。
- 在 StringBuilder 对象上调用 append(“二哥”),将 “二哥” 追加到 StringBuilder 中。
- 在 StringBuilder 对象上调用 append(“三妹”),将 “三妹” 追加到 StringBuilder 中。
- 在 StringBuilder 对象上调用 toString() 方法,将 StringBuilder 转换为一个新的字符串对象,内容为 “二哥三妹”。
本文原文来自CSDN
热门推荐
双十一囤票去西安,秋游正当时!
秋日探秘:新乡至锡崖沟最美骑行路线
广州珠海深圳三日游:从岭南文化到海滨浪漫的精彩之旅
来上海过年,这篇攻略就够了!
小叶赤楠养护秘籍大公开!
穿云越壑的空中奇迹:黄山新玉屏索道的建设历程
黄山索道怎么玩?这份攻略让你不踩雷!
放射科医生教你防CT辐射
最新研究:CT扫描增加儿童患癌风险,每多做一次风险增43%
CT扫描:风险与创新的平衡之道
CT扫描辐射:你真的了解它的风险吗?
黄鱼刺身:探索黄鱼新吃法 引领健康美食潮
药王谷一日游:孙思邈养生之旅
药王孙思邈曾在此采药:药王谷探秘
药王谷辛夷花节:一场春日里的视觉盛宴
春日药王谷:辛夷花开,等你来赴一场浪漫之约
东南亚最值得去的10个度假海岛
上海迪士尼乐园新玩法:达菲月、国庆烟花秀、疯狂动物城等你来!
淄博探秘:穿越千年的文化之旅与自然风光
重庆大足石刻:千年石刻艺术的传承与创新
枣庄锂电新能源产业崛起,引领经济高质量发展
探秘枣庄:台儿庄古城与甘泉寺的文化之旅
冬游青岛 | 老城漫步之旅
FDA推荐:奥氮平治疗精神分裂症的副作用管理
奥氮平副作用管理全攻略:从生活调整到医疗监测
琼海未来一周晴朗,最适合出游!
博鳌亚洲论坛永久会址:国际会议与绿色生态的完美融合
在博鳌享受悠闲时光的最佳方式
琼海潭门赶海节:体验最地道的南海渔耕文化
2025琼海春节游:蔡家大院百年庆典遇上博鳌小镇文化盛宴