Java 字符串优化:详解 String.intern() 方法
在Java编程中,字符串是最常用的数据类型之一,但是对于字符串的操作往往需要注意内存的使用和性能问题。本文我们将深入探讨Java中的字符串优化技术,重点关注于String类的intern()方法,以及如何正确地使用它来优化字符串操作
今日内容介绍,大约花费9分钟

昨天介绍了深入理解Java字符串常量池,介绍了String创建方法以及字符串常量池,今天介绍String一个方法String.intern(),大家可以看看美团写的美团技术团队深入解析 String.intern()文章,这是精品中精品,可是大家看了之后会觉得,我要放弃学习Java,因为有点看不懂,那么我简化给大家讲讲,前提是小伙伴已经理解昨天深入理解Java字符串常量池这篇文章一下几点:
-
1.使用双引号声明的字符串对象会保存在字符串常量池中
-
2.使用 new 关键字创建的字符串对象会先从字符串常量池中找,如果没找到就创建一个,然后再在堆中创建字符串对象;如果找到了,就直接在堆中创建字符串对象
思考:new String(“spring”) + new String(“葵花宝典”);操作如何进行性能优化
1.String.intern()简介
String str = new String("spring") + new String("葵花宝典");
如果要把上面str
内容存放到常量池,就需要使用intern()
方法
注意:Java 7时,字符串常量池从永久代中移动到了堆中,但是永久代还没有完全被移除。Java 8时,永久代被彻底移除。
Java 7之前和Java 7之后,String.intern()方法在执行时的策略发生了变化,这一变化直接影响了内存的利用方式
-
在Java 7之前,无论对象是否已经存在于堆中,String.intern()方法都会在字符串常量池中创建一个新的对象。
-
Java 7之后,由于字符串常量池被移动到了堆中,执行String.intern()方法时,如果堆中已经存在了该对象,字符串常量池中就不会创建新的对象,而是直接保存堆中对象的引用。这一优化节省了一部分内存空间。
2. String.intern()举例说明
可能小伙伴还没有理解,那么别怕,通过以下例子进行说明
2.1. new String(“spring葵花宝典”)
String str1 = new String("spring葵花宝典");
String str2= str1.intern();
System.out.println(str1 == str2);
思考:大家猜猜上面代码结果是什么?可能小伙伴猜不出来,那么我直接来解释一下
第一行,字符串常量池中会先创建一个spring葵花宝典
的对象,然后堆中会再创建一个spring葵花宝典
的对象,str1 引用的是堆中的对象。
第二行,str1 执行 intern() 方法,该方法会从字符串常量池中查找spring葵花宝典
,如果常量池中存在spring葵花宝典
字符串是否存在,因为第一行代码已经在字符串常量池创建spring葵花宝典
,所以 str2引用的是字符串常量池中的对象

str1 和 str2 的引用地址是不同的,str1一个来自堆,str2一个来自字符串常量池,所以输出的结果为 false。
2.2. new String(“spring”) + new String(“葵花宝典”)
String str1 = new String("spring") + new String("葵花宝典");
String str2= str1.intern();
System.out.println(str1 == str2);
思考:2.1输出结果是false,那么2.2结果也是false?
可能小伙伴猜错了,代码输出结果为true,这是为啥?
第一行,字符串常量池中会先创建两个对象spring
和葵花宝典
,然后堆中会再创建两个匿名对象spring
和葵花宝典
,最后还有一个spring葵花宝典
对象(一会解释),str1 引用的是堆中spring葵花宝典
对象。
第二行,str1 执行 intern() 方法,该方法会从字符串常量池中查找spring葵花宝典
对象是否存在,此时字符串常量池不存在,但是堆中存在

字符串常量池中保存的是堆中
spring葵花宝典
对象的引用,也就是说,str1 和 str2 的引用地址是相同,所以输出的结果为 true
具体步骤如下:
-
创建 “spring” 字符串对象,存储在字符串常量池中。
-
创建 “葵花宝典” 字符串对象,存储在字符串常量池中。
-
执行 new String(“spring”),在堆上创建一个字符串对象,内容为 “spring”。
-
执行 new String(“葵花宝典”),在堆上创建一个字符串对象,内容为 “葵花宝典”。
-
执行 new String(“spring”) + new String(“葵花宝典”),会创建一个 StringBuilder 对象,并将 “spring” 和 “葵花宝典” 追加到其中,然后调用 StringBuilder 对象的 toString() 方法,将其转换为一个新的字符串对象,内容为 “spring葵花宝典”。
这个新的字符串对象存储在堆上。
特别说明:编译器遇到 + 号这个操作符的时候,会将 new String(“spring”) + new String(“葵花宝典”) 编译代码如下:
new StringBuilder().append("spring").append("葵花宝典").toString();
实际步骤如下:
-
创建一个 StringBuilder 对象。
-
StringBuilder 对象上调用 append(“spring”),将 “spring” 追加到 StringBuilder 中。
-
在 StringBuilder 对象上调用 append(“葵花宝典”),将 “葵花宝典” 追加到 StringBuilder 中。
-
在 StringBuilder 对象上调用 toString() 方法,将 StringBuilder 转换为一个新的字符串对象,内容为 “spring葵花宝典”
3. String.intern()使用注意事项
尽管String.intern()方法能够有效地优化字符串操作,但是在使用时需要注意以下几点:
-
不要滥用intern()方法: 虽然intern()方法可以确保所有具有相同内容的字符串共享相同的内存空间,但也不要随意使用,因为字符串常量池是有大小限制的,过多的字符串可能会导致性能下降。
-
注意内存消耗: 使用intern()方法可能会增加内存消耗,因为它会将字符串对象存储到常量池中,而常量池是位于堆内存中的一部分。
-
考虑性能问题: 字符串常量池本质上是一个固定大小的StringTable,如果放进去的字符串过多,就会造成严重的哈希冲突,导致性能下降
如果您觉得本文不错,欢迎关注,点赞,收藏支持,您的关注是我坚持的动力!
感谢支持!如果本文对您有用,欢迎转发分享!
原文始发于微信公众号(springboot葵花宝典):Java 字符串优化:详解 String.intern() 方法
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/227188.html