Java 字符串常量池
首先看下面一段代码:
public class StringTest {
public static final String S = "Hello";
private String s = "Hello";
public static void main(String[] args) {
String s1 = "Hello";
String s2 = "Hello";
String s3 = new String("Hello");
String s4 = new String("Hello");
String s5 = new String("Hello").intern();
String s6 = "Hello".intern();
StringTest st = new StringTest();
System.out.println(s1 == st.s); // true
System.out.println(s1 == StringTest.S); // true
System.out.println(s1 == s2); // true
System.out.println(s1 == s3); // false
System.out.println(s3 == s4); // false
System.out.println(s1 == s5); // true
System.out.println(s1 == s6); // true
System.out.println(s1.equals(s2) + " " + s1.equals(s3) + " " + s3.equals(s4) + " " + s1.equals(s5) + " " + s1.equals(s6));
}
}
运行在 JDK 17 上.
这是除了 StringTest.S 这个静态字段之外的其他是 "Hello" 的字符串在内存的表示. 可以得出:
- 除了 s3, s4 其它都指向同一个内存对象.
- 所有这些字符串都指向同一个 byte[], 里面存储的是 “Hello” 的 ascii 码.
静态字段, 静态字段也同其它字面量一样, 都指向同一个.
这段代码里面, 有声明字面量(literal) 和 String 对象. 所有的字面量(常量或变量)都是指向内存字符串常量池的同一个字符串地址, 所以使用 == 对比也是相等的.
Java 常量池是什么?
Java 的字符串都是 Immutable 的, 也就是更改都会产生新的字符串. 常量池是在内存中开辟出来的一块专门存储字符串的空间. 由 String 类管理(native 代码). 它是一个很大的 HashMap 维护.
Java 常量池存在的意义什么?
所谓池, 就是共享同一份. 因为对很多程序来说, 很多字符串都是反复使用, 只要内存保存一份就好了.
为什么 new String() 不能返回常量池字符串?
常量池大小调节
可以看到如下参数, 默认是 65536. 调的太小, 容易产生hash 碰撞. 如果字符串不多, 调的太大, 占用太多空间.
uintx StringTableSize = 65536 {product} {default}