在Java中,字符串常量池(String Pool)是一个特殊的内存区域,用于存储字符串字面量和字符串对象的引用。字符串常量池的位置在不同的Java版本中有所变化。
Java 7 之前
在Java 7之前,字符串常量池位于方法区(Method Area)中。方法区是JVM内存模型的一部分,用于存储类的元数据、静态变量、常量池等。
Java 7 及之后
从Java 7开始,字符串常量池被移到了堆(Heap)中。这一变化主要是为了更好地管理内存,并允许垃圾回收器更有效地回收不再使用的字符串对象。
示例
考虑以下代码示例:
String str1 = "Hello";
String str2 = "Hello";
String str3 = new String("Hello");
System.out.println(str1 == str2); // true,因为str1和str2引用同一个字符串常量池中的对象
System.out.println(str1 == str3); // false,因为str3是新创建的对象
在这个例子中,str1
和str2
引用同一个字符串常量池中的对象,而str3
是新创建的对象,因此它们的引用不同。
字符串常量池的工作原理
-
字符串字面量:
- 当JVM遇到一个字符串字面量时,它会首先检查字符串常量池中是否已经存在相同内容的字符串。
- 如果存在,则返回常量池中的引用。
- 如果不存在,则在常量池中创建一个新的字符串并返回其引用。
-
new
关键字创建的字符串:- 使用
new
关键字创建的字符串对象不会进入字符串常量池,除非显式调用intern()
方法。 intern()
方法会将字符串对象放入字符串常量池,并返回常量池中的引用。
- 使用
示例:intern()
方法
String str1 = "Hello";
String str2 = new String("Hello");
String str3 = str2.intern();
System.out.println(str1 == str2); // false,因为str2是新创建的对象
System.out.println(str1 == str3); // true,因为str3是常量池中的引用
在这个例子中,str2
是新创建的对象,而str3
是通过intern()
方法返回的常量池中的引用。
总结
字符串常量池在Java 7之前位于方法区,从Java 7开始移到了堆中。字符串常量池用于存储字符串字面量和字符串对象的引用,通过字符串常量池可以实现字符串的共享,减少内存使用,提高性能。