1. 方法核心机制

intern() 方法会在堆内存中创建一个与该字符串对象完全相同的副本,并将其存入字符串常量池。⚠️ 需要注意的是:

  • 如果字符串常量池中已存在内容相同的字符串,则直接返回常量池中的引用
  • 不会在堆中创建新对象,避免内存浪费
  • 本质上是一个空间换时间的优化手段

2. 方法签名

public String intern()

✅ 无参数,返回字符串对象的常量池引用

3. 实战示例

@Test
public void whenIntern_thenCorrect() {
    String s1 = "abc";           // 直接指向常量池
    String s2 = new String("abc"); // 堆中新对象
    String s3 = new String("foo"); // 堆中新对象
    String s4 = s1.intern();     // 返回常量池引用
    String s5 = s2.intern();     // 返回常量池中已存在的"abc"
    
    assertFalse(s3 == s4);       // "foo"与"abc"不同
    assertTrue(s1 == s5);        // s1和s5都指向常量池中的"abc"
}

关键点解析

  1. s1 vs s2

    • s1 直接指向常量池中的 "abc"
    • s2 是堆中新创建的对象,内容虽相同但地址不同
  2. intern() 的作用

    • s2.intern() 发现常量池已有 "abc",直接返回其引用
    • s3.intern() 会将 "foo" 加入常量池并返回新引用
  3. 内存对比

    变量 存储位置 说明
    s1 常量池 字面量直接创建
    s2 堆内存 new 关键字创建
    s4 常量池 intern() 返回的引用
    s5 常量池 与 s1 相同的引用

⚠️ 踩坑提醒:过度使用 intern() 可能导致常量池内存溢出(PermGen/Metaspace OOM),仅在需要严格字符串复用时使用。