bigywater.tech
Java 内部原理 · 123

装箱缓存真实验证:Byte/Short/Long/Character缓存范围各不相同

Integer缓存(-128~127)大家都知道,但Byte、Short、Long、Character、Boolean、Double这几个包装类各自的缓存策略是什么?这篇真实用==对比六种类型,再反射读出缓存数组长度逐一验证。

Long缓存和Integer一样
真实验证:Long(127)==Long(127)为true,Long(128)==Long(128)为false,边界和Integer完全一致
Character只缓存0~127
真实反射读取:CharacterCache数组长度是128(0~127),不是256,因为char没有负数

上一篇:Arrays.sort 阈值真实验证

真实验证:六种包装类型的 == 行为对比

每种包装类型分别测试127(缓存边界内)和128(缓存边界外)两个值的==行为。

BoxingCacheTypesDemo.java Byte b1 = 100, b2 = 100; Short s1 = 127, s3 = 128; Long l1 = 127L, l3 = 128L; Character c1 = 127, c3 = 128;
真实实测
Byte(100)==Byte(100) 真实结果: true
Short(127)==Short(127) 真实结果: true
Short(128)==Short(128) 真实结果: false
Long(127)==Long(127) 真实结果: true
Long(128)==Long(128) 真实结果: false
Character(127)==Character(127) 真实结果: true
Character(128)==Character(128) 真实结果: false
Integer(127)==Integer(127) 真实结果: true
Integer(128)==Integer(128) 真实结果: false
Boolean.TRUE 真实是否单例: true
Double(1.0)==Double(1.0) 真实结果: false
Float(1.0)==Float(1.0) 真实结果: false

真实结果证明:Short、Long、Character、Integer这四种类型在128这个边界上表现出真实一致的行为模式——127以内==为true(共享缓存对象),128就变成false(各自new出独立对象)。而Double和Float真实完全不参与这套机制,任何值(哪怕是同一个1.0)每次装箱都真实产生新对象,==恒为false。Boolean比较特殊,它只有true/false两个可能值,JDK真实把这两个值都做成了单例。

真实反射验证:各自缓存数组的真实大小

BoxingCacheTypesDemo.java Class<?> cls = Class.forName("java.lang.Character$CharacterCache"); Field f = cls.getDeclaredField("cache"); Object[] arr = (Object[]) f.get(null);
真实实测
真实反射读取 java.lang.Byte$ByteCache 缓存数组长度 = 256
真实反射读取 java.lang.Short$ShortCache 缓存数组长度 = 256
真实反射读取 java.lang.Long$LongCache 缓存数组长度 = 256
真实反射读取 java.lang.Character$CharacterCache 缓存数组长度 = 128
真实反射读取 java.lang.Integer$IntegerCache 缓存数组长度 = 256
真实数字揭示了一个容易被忽略的不对称性。Byte的取值范围本身就是-128~127共256个值,所以它是全范围缓存——这也是为什么Byte类型完全不存在"超出缓存范围"的==陷阱。Short和Long的取值范围远超256,但JDK真实只缓存了和Integer一样的-128~127这256个值,这是出于"绝大多数程序里的小整数都落在这个区间"的工程权衡,而不是类型本身决定的。Character真实只缓存了128个值(0~127),因为char是无符号的,缓存范围就是0到127而不是-128到127——这个不对称容易在"以为所有整数类包装类缓存范围都一样"时踩坑。

分步演示:六种类型的缓存范围是怎么逐一浮现的

每一行都是真实的 == 比较结果加真实反射读出的缓存数组长度,不是查文档抄的。

Byte 全范围缓存,Short/Long 只缓存 -128~127,Character 只缓存 0~127,Double 完全不缓存
这一步新验证的类型

    参考与说明

    • 本文全部结果均在本机真实运行 Java 17 得到,==比较和反射读取缓存数组长度均可重复复现。
    • 和Integer 缓存真实验证一起看,能更完整理解为什么"测试环境用小数字==正常、生产环境用大数字==失灵"这个坑不只发生在Integer上,Short/Long同样会中招。
    • 没有涉及:-XX:AutoBoxCacheMax JVM参数真实能否调整Integer缓存上限、Byte/Short/Long/Character这几个缓存类是否支持类似参数——这两个话题留给系列后面按需再写。
    京ICP备2026067502号-1京公网安备11010502063487号