缓存池和常量池的区别
概念上的对比
| 特性 | 包装类缓存池 | 字符串常量池 |
|---|---|---|
| 适用对象 | Integer、Byte、Short、Long、Character等包装类 | String字符串 |
| 实现方式 | 内部静态数组缓存 | 特殊的内存区域(堆中或方法区) |
| 范围限制 | 通常只有-128~127(Integer可配置上限) | 任意字符串(通过intern()管理) |
| 创建方式 | 自动装箱或valueOf()时触发 | 字面量或intern()时触发 |
| 设计目的 | 避免频繁创建小范围对象 | 避免重复字符串占用内存 |
相似之处
都是享元模式的应用
两者都使用了享元模式,通过复用对象来节省内存和提高性能。
java
// 包装类缓存池
Integer a = 100; // 从缓存池取
Integer b = 100; // 从缓存池取
System.out.println(a == b); // true
// 字符串常量池
String s1 = "hello"; // 从常量池取
String s2 = "hello"; // 从常量池取
System.out.println(s1 == s2); // true
都提供手动管理方式
java
// 包装类:可以通过系统参数调整缓存上限
-Djava.lang.Integer.IntegerCache.high=200
// 字符串:可以通过intern()手动入池
String s = new String("hello").intern();
核心区别
缓存机制不同
包装类缓存池:
- 是预创建的,在类加载时就创建好-128~127范围内的所有对象
- 范围固定有限(虽然可以配置,但仍是有限的)
java
// IntegerCache源码简析
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// 预创建所有Integer对象
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
}
字符串常量池:
- 是动态的,在运行时动态添加
- 理论上无上限(受内存限制)
java
// 运行时动态添加到常量池
String s1 = "hello"; // 没有则创建
String s2 = "world"; // 动态添加
String s3 = "hello" + "world"; // 编译期优化,自动入池
存储位置不同(JVM视角)

处理机制不同
包装类缓存池 :只有通过valueOf()才会使用缓存
java
Integer a = 100; // 使用valueOf() → 缓存
Integer b = new Integer(100); // 强制创建新对象 → 不缓存
System.out.println(a == b); // false
字符串常量池:字面量自动使用常量池
java
String s1 = "hello"; // 常量池
String s2 = new String("hello"); // 堆中新对象
String s3 = s2.intern(); // 常量池引用
System.out.println(s1 == s2); // false
System.out.println(s1 == s3); // true
其他包装类的缓存范围
除了Integer,其他包装类也有类似的缓存机制:
| 包装类 | 缓存范围 | 说明 |
|---|---|---|
| Byte | -128 ~ 127 | 全部缓存(范围小) |
| Short | -128 ~ 127 | 同Integer |
| Long | -128 ~ 127 | 同Integer |
| Character | 0 ~ 127 | ASCII范围 |
| Boolean | TRUE, FALSE | 只有两个值 |
java
Long l1 = 127L;
Long l2 = 127L;
System.out.println(l1 == l2); // true
Long l3 = 128L;
Long l4 = 128L;
System.out.println(l3 == l4); // false
总结
缓存池和常量池确实是类似的思想------都是通过对象复用来优化性能。但它们的区别也很明显:
- 范围不同:缓存池针对小范围数值,常量池针对所有字符串
- 实现不同:缓存池是预创建数组,常量池是动态哈希表
- 位置不同:虽然都在堆中,但常量池有专门的管理结构
- 可控性不同:缓存池范围可配置但有限,常量池理论上无限制