Java String intern() 方法

2025 年 3 月 24 日 | 4 分钟阅读

Java String 类 intern() 方法 返回已驻留的字符串。它返回字符串的规范表示。

如果字符串是通过 new 关键字创建的,则可以使用它从内存中返回字符串。它会在 String 常量池中创建堆字符串对象的精确副本。

通过字符串存储的管理,Java 内置的 String.intern() 方法有助于最大限度地提高内存利用率并提高 Java 程序的整体效率。通过为字符串对象返回规范表示,intern() 方法可以确保所有相同的字符串具有相同的内存引用。当您拥有大量完全相同的字符串时,这特别有用,因为它会最小化内存占用并加快与 == 运算符的字符串比较速度。

签名

intern() 方法的签名如下所示

返回值

已驻留字符串

String.intern() 方法的需求和工作原理

在 Java 中创建字符串时,它会占用堆内存。此外,我们知道 String 类是不可变的。因此,无论何时使用 new 关键字创建字符串,都会在堆中为相应的字符串分配新内存,这与数组的内容无关。考虑以下代码片段。

println 语句打印 false,因为每个字符串字面量都分配了单独的内存。因此,在内存中创建了两个新的字符串对象,即 str 和 str1。它们持有不同的引用。

我们知道在 Java 中创建对象是一项昂贵的操作。因此,为了节省时间,Java 开发人员提出了字符串常量池 (SCP) 的概念。SCP 是堆内存中的一个区域。它包含唯一的字符串。为了将字符串放入字符串池,需要调用 intern() 方法。在字符串池中创建对象之前,JVM 会检查字符串是否已存在于池中。如果字符串存在,则返回其引用。

在上面的代码片段中,在 String 对象上调用了 intern() 方法。因此,在 SCP 中分配了内存。对于第二个语句,由于 str 和 str1 的内容相同,因此没有创建新的字符串对象。因此,为 str1 返回第一个语句中创建的对象的引用。因此,str 和 str1 都指向相同的内存。因此,print 语句打印 true。

Java String intern() 方法示例

示例

编译并运行

输出

false
true

说明

下面的代码展示了如何使用 Java 的 String.intern() 函数。它使用 new 关键字创建了一个名为 s1 的新 String 对象,该对象存储在堆内存中,还有一个名为 s2 的字符串字面量,该字面量直接存储在 String 常量池中。s1.intern() 的结果(返回字符串的规范表示)被分配给 s3 变量,从而保证 s3 引用 String 常量池中的与 s2 相同的字符串。由于 s1 和 s2 指向不同的内存位置,System.out.println(s1 == s2) 输出 false,而 System.out.println(s2 == s3) 输出 true,因为 s2 和 s3 引用 String 常量池中的同一个实例。

Java String intern() 方法示例 2

让我们再看一个例子来理解字符串驻留的概念。

示例

编译并运行

输出

true
false
true
false
true
false

说明

提供的代码演示了 Java 中 String.intern() 方法的行为及其对字符串引用的影响。它将 s1 初始化为字符串字面量“TpointTech”,该字面量存储在 String 常量池中,而 s2 设置为 s1.intern(),因此 s1 和 s2 都引用 String 常量池中的同一个实例。

使用 new 关键字创建了一个新的 String 对象 s3,它被放入堆内存中。s4 变量被赋值为 s3.intern(),使 s4 引用 String 常量池实例。因此,s1 == s2 和 s1 == s4 为 true,因为它们引用同一个池实例,而 s1 == s3 和 s2 == s3 为 false,因为 s3 是一个独立的堆对象。

最后,s2 == s4 为 true,因为它们都引用池实例,而 s3 == s4 为 false,因为 s3 和 s4 分别是堆和池中的不同引用。

注意事项

以下是关于 intern() 方法的一些重要注意事项

1) 字符串字面量总是调用 intern() 方法,无论是否显式地与字符串字面量一起提及 intern() 方法。例如,

2) 无论何时使用 new 关键字创建 String 对象,都会创建两个对象。例如,

在这里,由于使用了 new 关键字,一个对象创建在 SCP 之外的堆内存中。由于我们还有字符串字面量(“Hello World”);因此,会在 SCP 中创建一个对象,前提是字面量“Hello World”尚不存在于 SCP 中。