【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. 可控性不同:缓存池范围可配置但有限,常量池理论上无限制
相关推荐
折哥的程序人生 · 物流技术专研8 小时前
第4篇:Lambda 简化策略模式(Java 8+)
java·设计模式·策略模式·函数式编程·lambda·代码简化·扩充系列
researcher-Jiang9 小时前
高性能计算之OpenMP——超算习堂学习1
android·java·学习
西门吹-禅10 小时前
java springboot N+1问题
java·开发语言·spring boot
DLYSB_10 小时前
生命通道:如何用 HIS 医疗系统直连网络声光终端,打造“零延误”的危急值响应网关?
java·网络·数据库·报警灯
weixin_BYSJ198711 小时前
SpringBoot + MySQL 乒乓球运动员信息管理系统项目实战--附源码04954
java·javascript·spring boot·python·django·flask·php
AI小码11 小时前
LLM 应用的缓存工程:当每次 API 调用都在燃烧成本
java·人工智能·spring·计算机·llm·编程·api
Hui Baby12 小时前
Spring Security
java·后端·spring
IT笔记12 小时前
【Rust】Rust Match 模式匹配详解
java·开发语言·rust
ffqws_13 小时前
redis面试:如何保证双写一致
数据库·redis·缓存
我才是银古13 小时前
构建 Java GIS 工具库:从碎片化 API 到统一抽象的设计实践
java·gis·geotools·gdal·esri