访问量 ... 次
访客数 ... 人
当你在Java中写下Integer a = 12;
和int b = 12;
时,就像是给同一个数字穿上了不同的衣服,一个穿着对象的外套,一个保持着原始数据的质朴。
但它们的比较结果却暗藏玄机。
基本类型与包装类的差异,就像超市里的散装鸡蛋和盒装鸡蛋:
特性 | int(散装) | Integer(盒装) |
---|---|---|
存储位置 | 栈内存 | 堆内存 |
比较方式 | 直接比对鸡蛋大小 | 比对盒子地址或拆盒比鸡蛋 |
内存开销 | 固定4字节 | 对象头+实例数据≈16字节 |
当你在代码中写下Integer num = 12;
时,Java编译器悄悄施展魔法:
// 实际执行的代码
Integer num = Integer.valueOf(12);
这个valueOf()
方法就是通往缓存池的秘密通道!
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Java对-128~127
之间的Integer
对象进行缓存(可通过-XX:AutoBoxCacheMax
调整上限)。
当你要定义一个Integer a = 12;
,如果缓存池有现成的,直接取用(返回缓存对象);如果没有就创建新对象。
Integer a = 12; // 从缓存池获取
Integer b = new Integer(12); // 强制创建新对象
System.out.println(a == b); // false(地址不同)
Integer boxed = new Integer(12); // 新盒子
int primitive = 12; // 散装鸡蛋
System.out.println(boxed == primitive); // true ✅
// 实际比较过程
boxed.intValue() == primitive
Integer box1 = new Integer(100); // 手工包装
Integer box2 = new Integer(100); // 另一个手工包装
System.out.println(box1 == box2); // false ❌
Integer cache1 = 127; // 从共享货架拿盒子
Integer cache2 = 127; // 同一个盒子
System.out.println(cache1 == cache2); // true ✅
Integer big1 = 128; // 超出默认缓存
Integer big2 = 128; // 需要新盒子
System.out.println(big1 == big2); // false ❌
Integer boxed = 200;
int primitive = 200;
System.out.println(boxed == primitive); // true ✅
// 等价于 boxed.intValue() == primitive
// 若condition为true,返回自动装箱对象(超出缓存则新建)
// 若为false,返回new的新对象
// 两种情况下result都是不同对象
Integer result = condition ? 128 : new Integer(128);
比较3原则:
==
直接比较。
int a = 12;
int b = 12;
System.out.println(a == b); // 输出 true
Integer x = new Integer(12);
Integer y = new Integer(12);
System.out.println(x.equals(y)); // 输出 true
Integer m = 12; // 自动装箱
int n = 12;
System.out.println(m.equals(n)); // 输出 true
内存优化技巧:
Integer.valueOf(int)
:利用了Java的整数缓存机制(默认范围是-128到127),可以减少不必要的对象创建。
// 推荐写法(利用缓存)
Integer pageSize = Integer.valueOf(50);
new Integer(int)
:每次都会创建一个新的对象,增加内存开销。
// 不推荐写法(创建多余对象)
Integer pageCount = new Integer(50);
注意事项:
equals()
可以确保比较的是值而不是引用。
System.out.println(new Integer(12).equals(12)); // 输出 true
==
比较的适用场景:
==
比较结果正确。Integer i1 = 12; // 缓存范围内的自动装箱
Integer i2 = 12;
System.out.println(i1 == i2); // 输出 true
==
会自动拆箱。Integer i3 = 12;
int i4 = 12;
System.out.println(i3 == i4); // 输出 true
Integer
相加,导致GC频繁触发,最终引发服务器雪崩。数值操作无小事,类型选择需谨慎!
for (int i = 0; i < 1000000; i++) {
Integer value = Integer.valueOf(i); // 频繁创建对象
}