Integer / Long / 包装类型源码
概述
java.lang.Integer 和 java.lang.Long 是 Java 中最常用的两个数值包装类型,分别对 int 和 long 基本类型进行封装。它们都继承自抽象类 Number,实现了 Comparable 接口,并提供了丰富的数值转换、字符串解析、位运算工具方法。
本文从 JDK 源码出发,深入拆解包装类型的核心机制:缓存策略、字符串与数值互转、位运算黑科技、以及 IEEE 754 浮点编码。同时涉及 Number 抽象类、Boolean 缓存、CharacterCache 等姊妹类型的相关设计。
本文基于 OpenJDK 21 源码分析。
1. Number 抽象类 — 包装类型的共同基类
Integer、Long、Float、Double、Byte、Short 等所有数值包装类型都继承自 Number:
// java.lang.Number(部分源码)
public abstract class Number implements java.io.Serializable {
// 6 个抽象方法 — 将当前数值转换为指定类型
public abstract int intValue();
public abstract long longValue();
public abstract float floatValue();
public abstract double doubleValue();
// 默认实现在 int 范围内截断
public byte byteValue() {
return (byte) intValue();
}
public short shortValue() {
return (short) intValue();
}
}设计要点:
| 方法 | 类型 | 说明 |
|---|---|---|
intValue() | abstract | 转换为 int |
longValue() | abstract | 转换为 long |
floatValue() | abstract | 转换为 float |
doubleValue() | abstract | 转换为 double |
byteValue() | concrete | 默认通过 (byte)intValue() 实现 |
shortValue() | concrete | 默认通过 (short)intValue() 实现 |
Number 的存在使得所有数值包装类型可以被统一处理:
// 多态使用 — 任何数值包装类型均可转为 Number
void printNumber(Number n) {
System.out.println("int: " + n.intValue());
System.out.println("double: " + n.doubleValue());
}2. IntegerCache 的内部缓存
IntegerCache 是 Integer 的私有静态内部类,负责缓存常用 Integer 对象以避免重复创建:
// java.lang.Integer(部分源码)
private static class IntegerCache {
static final int low = -128;
static final int high;
static final Integer[] cache;
static {
// high 的值可以通过 JVM 参数 -XX:AutoBoxCacheMax=size 配置
int h = 127;
String integerCacheHighPropValue =
VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) - 1);
} catch (NumberFormatException nfe) {
// 如果配置值无法解析,使用默认值 127
}
}
high = h;
// 创建缓存数组,容量 = high - low + 1
cache = new Integer[(high - low) + 1];
int j = low;
for (int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}关键特性:
| 属性 | 值 | 说明 |
|---|---|---|
low | 固定 -128 | 下限不可调整 |
high | 默认 127 | 可通过 -XX:AutoBoxCacheMax=size 调整上限 |
| 配置属性名 | java.lang.Integer.IntegerCache.high | JVM 启动时读取并保存 |
| 数组大小 | high - low + 1 | 懒初始化,类加载时一次性创建 |
缓存区间示意图:
缓存数组索引: 0 1 ... 255
┌────┬────┬────┬────┬────┬────┬────┬────┐
缓存值: │-128│-127│-126│ ...│ 0 │ 1 │ ...│ 127│
└────┴────┴────┴────┴────┴────┴────┴────┘
low=-128 high=127Long 的缓存:Long.LongCache 结构类似,但区间固定为 [-128, 127],不支持调整:
// java.lang.Long(部分源码)
private static class LongCache {
static final Long[] cache;
static {
cache = new Long[-(-128) + 127 + 1]; // 固定长度 256
for (int i = 0; i < cache.length; i++)
cache[i] = new Long(i - 128);
}
}3. valueOf(int) 的缓存策略
3.1 Integer.valueOf(int)
// java.lang.Integer
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}- 如果
i在[-128, high]区间内,从IntegerCache.cache返回缓存对象 - 否则创建新的
Integer实例
3.2 Long.valueOf(long)
// java.lang.Long
public static Long valueOf(long l) {
final int offset = 128;
if (l >= -128 && l <= 127) { // will cache
return LongCache.cache[(int)l + offset];
}
return new Long(l);
}逻辑相同,但区间固定。
3.3 new Integer() vs Integer.valueOf()
| 方式 | 是否缓存 | 推荐 |
|---|---|---|
new Integer(100) | 不缓存,每次都新建对象 | ❌ 应避免 |
Integer.valueOf(100) | 命中缓存返回同一对象 | ✅ 推荐 |
Integer x = 100(自动装箱) | 等价于 Integer.valueOf(100) | ✅ 推荐 |
3.4 自动装箱的底层调用
Java 编译器会将自动装箱语法糖转换为 valueOf() 调用:
// 源代码
Integer x = 100; // 自动装箱
int y = x; // 自动拆箱
// 编译后等价于
Integer x = Integer.valueOf(100);
int y = x.intValue();这就是为什么以下代码的结果出乎许多人的意料:
Integer a = 100;
Integer b = 100;
System.out.println(a == b); // true — 命中缓存,同一对象
Integer c = 200;
Integer d = 200;
System.out.println(c == d); // false — 超出缓存范围,不同对象
// 务必使用 equals() 比较包装类型
System.out.println(c.equals(d)); // true3.5 姊妹类型的缓存
Boolean 更直接——它用两个静态常量实现缓存:
// java.lang.Boolean
public static final Boolean TRUE = new Boolean(true);
public static final Boolean FALSE = new Boolean(false);
public static Boolean valueOf(boolean b) {
return (b ? TRUE : FALSE);
}Character 也有 CharacterCache:
// java.lang.Character
private static class CharacterCache {
static final Character cache[] = new Character[127 + 1];
static {
for (int i = 0; i < cache.length; i++)
cache[i] = new Character((char)i);
}
}
// 缓存范围:0 ~ 127(ASCII 全部字符)
public static Character valueOf(char c) {
if (c <= 127) { // must cache
return CharacterCache.cache[(int)c];
}
return new Character(c);
}4. parseInt(String, radix) 的逐字符解析
Integer.parseInt(String, int) 将字符串按指定进制解析为 int,是数值解析的核心方法:
// java.lang.Integer
public static int parseInt(String s, int radix) throws NumberFormatException {
// 1. 进制合法性检查
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
throw new NumberFormatException("radix " + radix +
" out of range");
}
// 2. 空字符串检查
if (s == null || s.isEmpty()) {
throw new NumberFormatException("null or empty string");
}
// 3. 符号处理
int i = 0, len = s.length();
boolean negative = (s.charAt(0) == '-');
if (negative) {
i++;
if (len == 1) { // 只有负号
throw NumberFormatException.forInputString(s, len);
}
}
// 4. 核心:全程用负数累加,避免正数溢出
int limit = negative ? Integer.MIN_VALUE : -Integer.MAX_VALUE;
int result = 0;
while (i < len) {
int digit = Character.digit(s.charAt(i++), radix);
if (digit < 0) { // 非指定进制的合法数字字符
throw NumberFormatException.forInputString(s, len);
}
// 溢出检测:result * radix < limit
if (result < limit / radix) {
throw NumberFormatException.forInputString(s, len);
}
result *= radix;
// 溢出检测:result - digit < limit
if (result < limit + digit) {
throw NumberFormatException.forInputString(s, len);
}
result -= digit; // 注意是减法!
}
return negative ? result : -result;
}4.1 负数的处理技巧
解析全程使用负数累加是 parseInt 的精妙之处:
正数处理(直观但有问题): 负数处理(JDK 实际做法):
result = result * 10 + digit result = result * radix - digit
(全程 result 为负或零)
假设解析 "2147483648"(正好比 Integer.MAX_VALUE 大 1):
正数累加到末位会溢出 负数累加:
Integer.MAX_VALUE = 2147483647 limit = -2147483647
末位 digit=8 result = -2147483648 ✓
result * 10 + 8 > MAX_VALUE -2147483648 刚好等于 Integer.MIN_VALUE
→ 溢出 不会溢出!如果使用正数累加,Integer.MIN_VALUE(-2147483648)将无法被解析,因为其绝对值 2147483648 超出了 int 的正数范围。负数累加优雅地解决了这个问题。
4.2 Character.digit(char, int) 的映射
// java.lang.Character
public static int digit(char ch, int radix) {
// 对 '0'-'9' → 0-9
// 对 'a'-'z' → 10-35
// 对 'A'-'Z' → 10-35(大小写不敏感)
// 其他字符 → -1
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
return -1;
}
int val = getDigit(ch); // 内部查找表或计算
return (val < radix) ? val : -1;
}支持的进制范围:Character.MIN_RADIX = 2 到 Character.MAX_RADIX = 36。
5. toString(int, radix) 的数字转字符串
Integer.toString(int, int) 将整数按指定进制转换为字符串,与 parseInt 互为逆操作:
// java.lang.Integer
public static String toString(int i, int radix) {
// 1. 进制兜底
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX) {
radix = 10;
}
// 2. 快速路径:10 进制
if (radix == 10) {
return toString(i);
}
// 3. 负数统一处理
char[] buf = new char[33]; // int 最小值转二进制最多 33 字符(含负号)
boolean negative = (i < 0);
int charPos = 32;
if (!negative) {
i = -i; // 统一转负数处理
}
// 4. 核心循环:从低位到高位逐位取余
while (i <= -radix) {
buf[charPos--] = digits[-(i % radix)];
i /= radix;
}
buf[charPos--] = digits[-(i)]; // 最后一位
if (negative) {
buf[charPos--] = '-';
}
return new String(buf, charPos + 1, 32 - charPos);
}5.1 digits[] 数组映射
// java.lang.Integer
static final char[] digits = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z'
};5.2 负数处理的统一策略
与 parseInt 一样,toString 也将数值统一为负数处理,避免 Integer.MIN_VALUE 取绝对值溢出的问题:
parseInt: 全程用减法 (result -= digit),result 始终为负
toString: 先取负 (i = -i),用取余取模时取负 (-(i % radix))
原因:Integer.MIN_VALUE = -2147483648
Math.abs(Integer.MIN_VALUE) = -2147483648 <-- 溢出!
所以全程用负数运算最安全。5.3 示例:Integer.toString(n, 2) 二进制转换
以 i = -13, radix = 2 为例:
i = -13, negative = true
循环迭代:
1. i = -13, i <= -2? true, digit = -(-13 % 2) = 1, buf[32] = '1', i = -13 / 2 = -6
2. i = -6, i <= -2? true, digit = -(-6 % 2) = 0, buf[31] = '0', i = -6 / 2 = -3
3. i = -3, i <= -2? true, digit = -(-3 % 2) = 1, buf[30] = '1', i = -3 / 2 = -1
4. i = -1, i <= -2? false
buf[29] = digits[-(-1)] = '1'
加上负号:
buf[28] = '-'
结果: "1101" → "-1101"6. highestOneBit(int) 位运算
Integer.highestOneBit(int) 返回只保留最高位 1 的数值,是位运算中的经典算法:
// java.lang.Integer
public static int highestOneBit(int i) {
// 将最高位 1 右边的所有位都填充为 1
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);
// 减去右移一位的结果,只保留最高位
return i - (i >>> 1);
}6.1 逐行拆解
以 i = 0b_0000_0000_0000_0000_0000_0100_0000_0000(即 1024)为例:
i = 0000 0000 0000 0000 0000 0100 0000 0000
i >>= 1 = 0000 0000 0000 0000 0000 0010 0000 0000
i |= (i>>1) = 0000 0000 0000 0000 0000 0110 0000 0000 ← 最高两位已填充
i >>= 2 = 0000 0000 0000 0000 0000 0001 1000 0000
i |= (i>>2) = 0000 0000 0000 0000 0000 0111 1000 0000 ← 最高四位已填充
i >>= 4 = 0000 0000 0000 0000 0000 0000 0111 1000
i |= (i>>4) = 0000 0000 0000 0000 0000 0111 1111 1000 ← 最高八位已填充
i >>= 8 = 0000 0000 0000 0000 0000 0000 0000 0111
i |= (i>>8) = 0000 0000 0000 0000 0000 0111 1111 1111 ← 最高十六位已填充
i >>= 16 = 0000 0000 0000 0000 0000 0000 0000 0000
i |=(i>>16) = 0000 0000 0000 0000 0000 0111 1111 1111 ← 全部填充完毕
i >>> 1 = 0000 0000 0000 0000 0000 0011 1111 1111
i - (i>>>1) = 0000 0000 0000 0000 0000 0100 0000 0000 ← 只保留最高位 16.2 Long.highestOneBit(long)
Long 版的逻辑相同,只是多了一行 i >>> 32:
// java.lang.Long
public static long highestOneBit(long i) {
i |= (i >> 1);
i |= (i >> 2);
i |= (i >> 4);
i |= (i >> 8);
i |= (i >> 16);
i |= (i >> 32); // long 是 64 位,需要再多一轮
return i - (i >>> 1);
}6.3 应用场景:HashMap 的 tableSizeFor
HashMap 使用 tableSizeFor 将给定容量对齐到 2 的幂,其核心就是 Integer.highestOneBit:
// java.util.HashMap
static final int tableSizeFor(int cap) {
int n = -1 >>> Integer.numberOfLeadingZeros(cap - 1); // 相当于 highestOneBit
// ... 实际上这里的实现更巧妙
}HashMap 的容量始终是 2 的幂,这使得 (n - 1) & hash 可以替代取模运算。而 highestOneBit 就是将一个数调整为不大于它本身的 2 的最大幂。
7. numberOfLeadingZeros(int) 二分查找前导零
Integer.numberOfLeadingZeros(int) 返回 32 位 int 中最高位 1 之前有多少个 0。如果输入为 0,则返回 32。
// java.lang.Integer
public static int numberOfLeadingZeros(int i) {
if (i <= 0)
return i == 0 ? 32 : 0; // 负数最高位为 1,前导零为 0
int n = 1; // 至少有一个前导零
// 二分法:每次判断高半部分是否全为 0
if (i >>> 16 == 0) { n += 16; i <<= 16; } // 高 16 位全零 → 左移 16 位
if (i >>> 24 == 0) { n += 8; i <<= 8; } // 高 8 位全零 → 左移 8 位
if (i >>> 28 == 0) { n += 4; i <<= 4; } // 高 4 位全零 → 左移 4 位
if (i >>> 30 == 0) { n += 2; i <<= 2; } // 高 2 位全零 → 左移 2 位
n -= i >>> 31; // 最后检查最高位
return n;
}7.1 二分法执行过程
以 i = 0x0000001A(0b_0000_0000_0000_0000_0000_0000_0001_1010)为例:
i = 0000 0000 0000 0000 0000 0000 0001 1010
↑最高位 1 在第 28 位
Step 1: i >>> 16 == 0? YES → n=17, i <<=16
i = 0000 0000 0001 1010 0000 0000 0000 0000
↑最高位 1 现在在第 12 位
Step 2: i >>> 24 == 0? YES → n=25, i <<=8
i = 0001 1010 0000 0000 0000 0000 0000 0000
↑最高位 1 现在在第 4 位
Step 3: i >>> 28 == 0? YES → n=29, i <<=4
i = 1010 0000 0000 0000 0000 0000 0000 0000
↑最高位 1 现在在第 31 位
Step 4: i >>> 30 == 0? YES → n=31, i <<=2
i = 1000 0000 0000 0000 0000 0000 0000 0000
↑
Step 5: n -= i >>> 31 i>>>31 = 1, n = 31 - 1 = 30
结果:numberOfLeadingZeros(0x1A) = 277.2 时间复杂度分析
| 方法 | 比较次数 | 时间复杂度 |
|---|---|---|
| 朴素循环逐位右移 | 最多 32 次 | O(n) |
| 二分法(JDK 实现) | 5 次 | O(log n) |
对于 long 的 numberOfLeadingZeros(long),需要 6 次二分判断。
7.3 应用场景
numberOfLeadingZeros 是许多位操作方法的底层辅助,如 highestOneBit 的另一种实现思路、Float.floatToIntBits 中的归一化处理等。它也常用于实现 floor(log2(x)):
// floor(log2(x)) = 31 - numberOfLeadingZeros(x)
// 例如 x=8(0b1000), numberOfLeadingZeros=28, 31-28=3 = log2(8) ✓8. reverseBytes(int) 字节翻转
Integer.reverseBytes(int) 将 32 位整数的 4 个字节按顺序翻转(Big-Endian ↔ Little-Endian):
// java.lang.Integer
public static int reverseBytes(int i) {
return (i << 24) |
((i & 0xFF00) << 8) |
((i >>> 8) & 0xFF00) |
(i >>> 24);
}8.1 逐层拆解
以 i = 0xAABBCCDD 为例:
原值: 0xAABBCCDD
内存布局: [AA] [BB] [CC] [DD] (大端: 高位 → 低位)
[DD] [CC] [BB] [AA] (小端: 低位 → 高位)
操作拆解:
① i << 24 = 0xDD000000 第 4 字节移到第 1 字节位置
② (i & 0xFF00) << 8
i & 0xFF00 = 0x0000CC00
<< 8 = 0x00CC0000 第 3 字节移到第 2 字节位置
③ (i >>> 8) & 0xFF00
i >>> 8 = 0x00AABBCC
& 0xFF00 = 0x0000BB00 第 2 字节移到第 3 字节位置
④ i >>> 24 = 0x000000AA 第 1 字节移到第 4 字节位置
① | ② | ③ | ④ = 0xDDCCBBAA ✔ 字节完全翻转8.2 Long.reverseBytes(long) 的 64 位版本
// java.lang.Long
public static long reverseBytes(long i) {
i = (i & 0x00FF00FF00FF00FFL) << 8 | (i >>> 8) & 0x00FF00FF00FF00FFL;
i = (i & 0x0000FFFF0000FFFFL) << 16 | (i >>> 16) & 0x0000FFFF0000FFFFL;
return (i << 32) | (i >>> 32);
}64 位版本使用了分层翻转策略:先交换相邻字节对,再交换相邻短整型对,最后交换上下 32 位。
8.3 应用场景:网络字节序转换
// 网络字节序(Big-Endian)与主机字节序(Little-Endian)转换
// x86/x64 架构使用小端序
// 读取网络数据流时
int networkOrder = dis.readInt(); // 网络字节序
int hostOrder = Integer.reverseBytes(networkOrder); // 转为主机字节序
// 或者使用 java.nio.ByteBuffer(更推荐)
int value = ByteBuffer.wrap(bytes).order(ByteOrder.BIG_ENDIAN).getInt();9. Float.floatToIntBits() 的 IEEE 754 编码
9.1 floatToIntBits() 和 floatToRawIntBits()
// java.lang.Float
public static int floatToIntBits(float value) {
// 关键区别:将 NaN 统一为 "规范的" NaN 位模式
if (!isNaN(value)) {
return floatToRawIntBits(value);
}
return 0x7fc00000; // 规范的 NaN(quiet NaN)
}
// floatToRawIntBits() 是 native 方法,直接返回 IEEE 754 位模式
public static native int floatToRawIntBits(float value);两个方法的区别:
| 方法 | NaN 处理 | 其他值 |
|---|---|---|
floatToRawIntBits() | 保留所有 NaN 的位模式(包括 signaling NaN) | 相同 |
floatToIntBits() | 所有 NaN 统一返回 0x7fc00000 | 相同 |
9.2 IEEE 754 单精度浮点格式
32 位单精度浮点数 (float):
┌─────┬─────────┬──────────────────────────────┐
│ 1位 │ 8位 │ 23位 │
│ 符号 │ 指数 │ 尾数 │
│ s │ e │ m │
└─────┴─────────┴──────────────────────────────┘IEEE 754 单精度公式:
value = (-1)^s × 2^(e-127) × 1.m (规格化数, e ≠ 0)
value = (-1)^s × 2^(-126) × 0.m (非规格化数, e = 0)
特殊值:
e = 255, m = 0 → ±∞ (无穷大)
e = 255, m ≠ 0 → NaN (非数)示例:将 3.14f 转为位模式:
3.14 的二进制 ≈ 11.001000111... × 2^0
规格化: 1.1001000111... × 2^1
s = 0
e = 1 + 127 = 128 = 0b10000000
m = 10010001111010111000011 (23 位)
结果: 0 | 10000000 | 10010001111010111000011
= 0x4048F5C39.3 Double.doubleToLongBits() 双精度版本
// java.lang.Double
public static long doubleToLongBits(double value) {
if (!isNaN(value)) {
return doubleToRawLongBits(value);
}
return 0x7ff8000000000000L; // 规范的 NaN
}双精度 IEEE 754 格式:
64 位双精度浮点数 (double):
┌─────┬──────────┬─────────────────────────────────────────────┐
│ 1位 │ 11位 │ 52位 │
│ 符号 │ 指数 │ 尾数 │
│ s │ e │ m │
└─────┴──────────┴─────────────────────────────────────────────┘| 规格 | 单精度 (float) | 双精度 (double) |
|---|---|---|
| 总位数 | 32 | 64 |
| 符号位 | 1 | 1 |
| 指数位 | 8(偏置 127) | 11(偏置 1023) |
| 尾数位 | 23(含 1 位隐含位) | 52(含 1 位隐含位) |
| 精度 | 约 7 位十进制 | 约 16 位十进制 |
| 范围 | ±1.4E-45 ~ ±3.4E+38 | ±4.9E-324 ~ ±1.8E+308 |
9.4 典型应用:哈希计算
// Float.hashCode() 和 Double.hashCode() 依赖位模式
public int hashCode() {
return Float.floatToIntBits(value); // Float
}
public int hashCode() {
return (int)(Double.doubleToLongBits(value) ^
(Double.doubleToLongBits(value) >>> 32)); // Double
}这使得浮点数可以用作 HashMap 的键,尽管需要注意精度问题。
10. 包装类型的不可变性设计
所有包装类型都被设计为**不可变(immutable)**对象,一旦创建其内部值不可修改。
10.1 不可变性的实现
// java.lang.Integer
public final class Integer extends Number implements Comparable<Integer> {
// final 字段 — 一旦赋值不可修改
private final int value;
// 构造器 — 创建时赋值
@Deprecated(since="9", forRemoval=true)
public Integer(int value) {
this.value = value;
}
// 所有方法都返回新对象,不修改自身
public Integer plus(Integer other) { // 假设有这个方法
return Integer.valueOf(this.value + other.value); // 返回新对象
}
}10.2 不可变性的好处
| 特性 | 说明 |
|---|---|
| 线程安全 | 无需同步即可在多个线程间共享 |
| 缓存可行 | 值不变,对象可安全复用(IntegerCache 的基础) |
| 适合做 Map 键 | hashCode 不会变化,放入 Map 后不会"丢失" |
| 无防御性拷贝 | 方法返回包装类型时无需担心调用方修改 |
10.3 Integer 的类签名结构
java.lang.Integer
extends java.lang.Number ← 数值抽象基类
implements java.lang.Comparable ← 可比较排序
关键字段:
private final int value ← 包装的核心 int 值
public static final int MIN_VALUE = -2147483648
public static final int MAX_VALUE = 2147483647
public static final int BYTES = 4 (JDK 8+)
public static final int SIZE = 32
内部类:
private static class IntegerCache ← 缓存 [-128, high]11. 关键类结构一览
java.lang.Number ← 抽象基类
├── abstract int intValue()
├── abstract long longValue()
├── abstract float floatValue()
├── abstract double doubleValue()
├── byte byteValue() → (byte)intValue()
├── short shortValue() → (short)intValue()
│
├── java.lang.Integer ← final, extends Number, implements Comparable
│ ├── final int value ← 核心字段
│ ├── static final int MIN_VALUE = -2147483648
│ ├── static final int MAX_VALUE = 2147483647
│ ├── static final int SIZE = 32
│ ├── static final int BYTES = 4
│ ├── private static class IntegerCache ← 内部缓存
│ │ ├── static final int low = -128
│ │ ├── static final int high ← 默认 127,可调
│ │ └── static final Integer[] cache ← 缓存数组
│ ├── static Integer valueOf(int) ← 缓存入口
│ ├── static int parseInt(String, int) ← 逐字符解析
│ ├── static String toString(int, int) ← 进制转换
│ ├── static int highestOneBit(int) ← 位运算
│ ├── static int numberOfLeadingZeros(int) ← 前导零
│ ├── static int reverseBytes(int) ← 字节翻转
│ └── (equals, hashCode, compareTo) ← 基于 value
│
├── java.lang.Long ← final, extends Number, implements Comparable
│ ├── final long value
│ ├── private static class LongCache ← 缓存 [-128, 127]
│ └── (同名静态方法,操作 long 版本)
│
├── java.lang.Float ← IEEE 754 单精度
│ ├── static native int floatToRawIntBits(float)
│ └── static int floatToIntBits(float) ← NaN 归一化
│
├── java.lang.Double ← IEEE 754 双精度
│ ├── static native long doubleToRawLongBits(double)
│ └── static long doubleToLongBits(double) ← NaN 归一化
│
├── java.lang.Boolean ← 两个静态常量
│ ├── public static final Boolean TRUE
│ └── public static final Boolean FALSE
│
└── java.lang.Character ← CharacterCache [0, 127]
└── private static class CharacterCache总结
缓存策略贯穿包装类型设计:
IntegerCache(可调上限)、LongCache(固定 -128~127)、CharacterCache(0~127)、Boolean的TRUE/FALSE常量,均通过valueOf()方法提供缓存入口,自动装箱语法糖也委托给valueOf()。负数统一处理是 parseInt/toString 的核心技巧:解析和格式化时全程使用负数运算,安全避开
Integer.MIN_VALUE取绝对值溢出的陷阱。位运算方法的二分法思想:
numberOfLeadingZeros用 5 次二分判断替代 32 次循环(O(log n) vs O(n)),highestOneBit通过"填充所有低位 → 减去右移结果"的巧妙方式提取最高位。字节翻转的位掩码技术:
reverseBytes使用一次移位 + 掩码完成 4 字节交换,对于网络字节序转换至关重要。IEEE 754 编码的统一 NaN 处理:
floatToIntBits将所有 NaN 位模式统一为0x7fc00000(quiet NaN),确保哈希计算的一致性。不可变性是包装类型的基础设计:
final字段 + 只返回新对象的所有方法,使得缓存、线程安全、Map 键等特性得以成立。Number抽象类提供了多态基础:6 个类型转换方法(4 个抽象 + 2 个具体实现)使所有数值包装类型可以统一处理。