【Java SE】缓存池和常量池的区别

缓存池和常量池的区别

概念上的对比

特性 包装类缓存池 字符串常量池
适用对象 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

总结

缓存池和常量池确实是类似的思想------都是通过对象复用来优化性能。但它们的区别也很明显:

  1. 范围不同:缓存池针对小范围数值,常量池针对所有字符串
  2. 实现不同:缓存池是预创建数组,常量池是动态哈希表
  3. 位置不同:虽然都在堆中,但常量池有专门的管理结构
  4. 可控性不同:缓存池范围可配置但有限,常量池理论上无限制
相关推荐
咖啡八杯1 天前
GoF设计模式——工厂方法模式
java·后端·设计模式
代码羊羊1 天前
Rust 迭代器完全通俗易懂指南(零基础全覆盖)
java·开发语言·rust
MY_TEUCK1 天前
【Java 后端】SpringBoot 登录认证与会话跟踪实战(JWT + Filter/Interceptor)
java·开发语言·spring boot
今天长肉了吗1 天前
银行风控项目踩坑实录:指标跑了6小时,风险评分全挂了
java
随读手机1 天前
多式联运信息交互平台完整方案(2026版)
java·ai·eclipse·云计算·区块链
许彰午1 天前
03-二叉树——从递归遍历到非递归实现
java·算法
nj01281 天前
Spring 循环依赖详解:三级缓存、早期引用、AOP 代理与懒加载
java·spring·缓存
野生技术架构师1 天前
2026年最全Java面试题及答案汇总(建议收藏,面试前看这篇就够了)
java·开发语言·面试
一只叫煤球的猫1 天前
ThreadForge 源码解读一:ThreadScope 如何把并发任务放进清晰边界?
java·面试·开源
洛_尘1 天前
Python 5:使用库
java·前端·python