Java 字符串引用(String Interning)

兄弟姐妹们有没有人讲详细点的我想讲解下,Java 字符串引用(String Interning)
最新回答
小阳光温暖我╮

2026-10-18 11:07:46

Java 字符串引用(String Interning)是指 JVM 通过维护一个字符串常量池(String Pool)来优化字符串内存分配的机制。

核心机制
  1. 不可变性Java 的 String 类被设计为不可变(immutable),即一旦创建,其内容无法修改。这一特性使得字符串可以被安全地共享和复用。

  2. 字符串常量池JVM 在堆内存中维护一个特殊的存储区域——字符串常量池。当通过字面量(如 String s = "abc")创建字符串时:

    JVM 首先检查池中是否存在相同内容的字符串。

    若存在:直接返回池中已有对象的引用(避免重复创建)。

    若不存在:在池中创建新字符串对象,并返回其引用。

  3. new 关键字的区别通过 new String("abc") 显式创建的字符串不会自动加入常量池,即使池中已存在相同内容。此时会强制在堆中新建对象,导致引用不同。

关键代码示例1. 字面量共享引用String s1 = "HoneyMoose";String s2 = "HoneyMoose";System.out.println(s1 == s2); // 输出 true(引用相同)
  • 原因:s1 和 s2 均指向常量池中的同一对象。
2. new 关键字创建独立对象String s3 = new String("HoneyMoose");String s4 = new String("HoneyMoose");System.out.println(s3 == s4); // 输出 false(引用不同)
  • 原因:new 强制在堆中创建新对象,即使内容相同。
3. 手动调用 intern()String s5 = new String("HoneyMoose").intern();String s6 = "HoneyMoose";System.out.println(s5 == s6); // 输出 true
  • 原因:intern() 方法将字符串显式加入常量池,并返回池中引用。
内存优化与性能影响
  • 优势:通过复用常量池中的字符串,减少内存占用(尤其适用于重复字符串)。
  • 风险:过度使用 intern() 或大量动态字符串可能导致常量池膨胀(PermGen/Metaspace 内存问题)。
验证方法

可通过以下代码验证字符串引用是否相同:

@Testpublic void whenCreatingConstantStrings_thenTheirAddressesAreEqual() { String constantString1 = "HoneyMoose"; String constantString2 = "HoneyMoose"; assertThat(constantString1).isSameAs(constantString2); // 断言通过}
  • 结果:constantString1 和 constantString2 指向同一内存地址。
总结
  • 字符串引用(Interning) 是 JVM 对字符串字面量的优化机制,通过常量池复用对象。
  • 关键点:

    字面量字符串自动加入常量池。

    new String() 创建新对象,不共享引用。

    intern() 可手动将字符串加入池中。

  • 应用场景:适合处理大量重复字符串(如配置文件中的固定值),但需谨慎使用以避免内存问题。

(示意图:字符串常量池与堆内存的关系)