Java 里基本类型不能直接当对象用,包装类就是为这事儿存在的。int 对应 Integer,char 对应 Character,其余的包装类名就是把首字母大写。
从 JDK 1.5 开始有了自动装箱和拆箱,编译器会在需要时帮你调用 valueOf() 或 xxxValue()——写起来是省事了,但有些坑就藏在'自动'背后。
自动装箱带来的三个实际问题
1. 性能开销比想象中大
Integer i = 0; 这样的代码在循环里每次都会调 Integer.valueOf(0),如果循环次数很多,创建的大量 Integer 对象会给 GC 不小的压力。拆箱也一样,看起来只是 int j = i,其实调了 intValue()。高频计算路径上我一般直接用基本类型,或者用 int[] 而不是 Integer[]。
2. 空指针总是出其不意
Integer nullInt = null;
int value = nullInt; // NPE
当数据库字段或 JSON 字段允许 null 时,自动拆箱就很容易炸。遍历集合做累加时尤其要小心:
List<Integer> list = new ArrayList<>();
list.add(10);
list.add(null);
int sum = 0;
for (Integer i : list) {
sum += i; // 这里可能 NPE
}
我的习惯是显式判空再拆箱,或者用 Optional 包装一下,虽然啰嗦但线上少很多事故。
3. == 比 equals 靠不住
Integer 在 -128 到 127 之间会走缓存池,所以 Integer a = 127; Integer b = 127; a == b 是 true。但 Integer a = 128; Integer b = 128; a == b 就变成 false 了——有点反直觉。不管什么情况,比较值一律用 equals(),别依赖 JVM 的缓存实现。
泛型怎么让集合更安全
没有泛型的时候,ArrayList 就是个 Object 容器,取元素得强转,类型错了编译期不报错,留到运行时一个 ClassCastException 甩脸上。泛型在编译期做类型检查,既安全又可读。
泛型类和泛型方法的用法很直接:
public class Box<T> {
T content;
{
.content = content;
}
T {
content;
}
}
Box<Integer> integerBox = <>();
integerBox.setContent();
integerBox.getContent();


