【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. 可控性不同:缓存池范围可配置但有限,常量池理论上无限制
相关推荐
扶风ff7 分钟前
练题簿在线免费刷题:会员线下组卷、Word 试卷与成绩导入,课堂检测更方便
java·开发语言·算法·小程序·word
鱼宵7 分钟前
Spring AI 可观测与透明化:traceId 串起全链路,思考过程实时直播给用户
java·人工智能·spring·链路追踪·springai
Raas10022 分钟前
AI网关能做语义缓存吗?MAI Gateway(魔芋企业级AI网关)实战能力深度解读
java·后端·spring
天空鸟_时光不老29 分钟前
13-亮点提炼:把技术说辞翻译成业务价值
java·spring boot·spring·spring cloud·mybatis
小蒜学长33 分钟前
基于SpringBoot+Vue的租房管理系统的设计与实现(代码+数据库+LW)
java·数据库·spring boot·后端·租房管理
C++ 老炮儿的技术栈35 分钟前
char (*csConnectName)[256]; 和 char csConnectName [256] 有什么区别
java·c语言·开发语言·c++·人工智能·算法·c
洋就在江州38 分钟前
gitlab-cicd 离线集成——springboot-cicd (非docker形式,shell形式)
java·spring boot·后端·ci/cd·gitlab·gitlab-runner
CEZ1 小时前
JeeWMS 开源 WMS 全景导览:一套 Java 仓库管理系统从单据流到代码入口的阅读地图
java·开源
Nebula_g1 小时前
JavaSE加强:线程Thread(线程安全重点)
java·开发语言·jvm·算法·javase·技术栈
令狐少侠20111 小时前
centos7 下,使用docker 部署IOT 调试平台,ThingsBoard 并完美启动
java·spring boot·iot