Java 字符串优化:详解 String.intern() 方法

Java 字符串优化:详解 String.intern() 方法

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

今日内容介绍,大约花费9分钟

Java 字符串优化:详解 String.intern() 方法
image

昨天介绍了深入理解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引用的是字符串常量池中的对象

Java 字符串优化:详解 String.intern() 方法
image

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葵花宝典对象是否存在,此时字符串常量池不存在,但是堆中存在

Java 字符串优化:详解 String.intern() 方法
image

字符串常量池中保存的是堆中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

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!