【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. 可控性不同:缓存池范围可配置但有限,常量池理论上无限制
相关推荐
Wy_编程15 小时前
redis 客户端编程
数据库·redis·缓存
凭君语未可15 小时前
从静态代理走向动态代理:理解 JDK 动态代理的本质
java·开发语言
黑风风16 小时前
在 Windows 上设置 MAVEN_HOME 环境变量(完整指南)
java·windows·maven
Rsun0455116 小时前
15、Java 观察者模式从入门到实战
java·python·模板方法模式
珹洺16 小时前
Java-Spring入门指南(二十三)俩万字超详细讲解利用IDEA手把手教你实现SSM(Spring + SpringMVC + MyBatis)整合,并构建第一个SSM基础系统
java·spring·intellij-idea
yaaakaaang16 小时前
十九、观察者模式
java·观察者模式
小碗羊肉16 小时前
【从零开始学Java | 第三十八篇】序列化流(Object Stream)
java·开发语言
亚历克斯神16 小时前
Java 23 虚拟线程进阶:深度探索与实战
java·spring·微服务
想带你从多云到转晴16 小时前
02、JAVAEE--多线程(二)
java·开发语言·javaee
AIoT科技物语16 小时前
免费开源!50+算法,Java基于YOLO框架的视频AI识别算法平台,适配低空无人机巡检、摄像头安防场景
java·人工智能·算法·yolo·开源