在 Java 中,String 的 intern() 方法是一个非常重要的概念,它与 字符串常量池(String Constant Pool)密切相关。为了更好地理解它的工作原理,我们可以从实际例子出发。
1. String Intern() 方法概述
intern() 方法的作用是:
- 如果字符串常量池中已经存在一个等价于当前
String对象的字符串,则返回常量池中的字符串的引用。 - 如果常量池中没有这个字符串,则将该字符串添加到常量池,并返回该字符串的引用。
这个方法主要用于优化内存,因为 Java 会确保相同内容的字符串只在内存中存在一个副本。
2. 常量池与 intern()
在 Java 中,所有通过字面量创建的字符串都会被自动加入到 字符串常量池 中。例如:
String s1 = "java";
String s2 = "java";
这里,s1 和 s2 都指向常量池中的 "java" 字符串。
如果你显式调用 intern() 方法,则会强制将一个非字面量的字符串加入到常量池中,或者返回常量池中已存在的等价字符串。
3. 具体示例分析
让我们通过一个具体的例子来详细分析 intern() 的工作原理:
public class StringInternTest {
public static void main(String[] args) {
// 字面量创建的字符串
String s1 = "hello";
String s2 = "hello"; // 与s1引用相同
// 使用new关键字创建的字符串
String s3 = new String("hello");
// 使用intern()方法
String s4 = s3.intern();
// 打印是否引用相同
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s1 == s4); // true
}
}
4. 代码逐步分析
-
String s1 = "hello";- 这是一个字面量字符串,它会直接指向字符串常量池中的
"hello"。
- 这是一个字面量字符串,它会直接指向字符串常量池中的
-
String s2 = "hello";- 由于字面量
"hello"已经在常量池中,s2会直接引用常量池中的"hello",与s1指向同一个内存位置。
- 由于字面量
-
String s3 = new String("hello");- 这是通过
new关键字创建的字符串,它不直接指向常量池中的"hello",而是指向堆内存中的一个新对象。虽然"hello"这个字符串字面量已存在常量池中,但new String("hello")会在堆中创建一个新的String对象。
- 这是通过
-
String s4 = s3.intern();s3是通过new创建的字符串对象,调用intern()方法时,会检查常量池中是否已经存在"hello"。- 由于常量池中已经有
"hello",所以intern()方法返回常量池中的"hello",并将s4引用指向常量池中的字符串"hello"。
5. 输出结果分析
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s1 == s4); // true
s1 == s2输出true:s1和s2都指向常量池中的"hello",它们是同一个对象。s1 == s3输出false:s3是通过new创建的字符串,它指向堆内存中的一个新对象,而s1指向常量池中的字符串,因此它们不是同一个对象。s1 == s4输出true:s4是通过s3.intern()获取的,它指向常量池中的"hello",与s1相同,因此它们是同一个对象。
6. 总结
- 字面量创建的字符串会直接加入常量池。
- 使用
new创建的字符串会指向堆内存中的新对象,不会直接添加到常量池。 - 调用
intern()方法时,如果常量池中已经存在该字符串,则返回常量池中的引用;如果不存在,则将其添加到常量池中,并返回引用。
intern() 的关键作用是 优化内存,避免重复存储相同内容的字符串。如果有大量相同内容的字符串使用 intern(),可以节省内存。