Java包装类核心痛点是缓存陷阱、装箱拆箱隐式行为、泛型与null处理;Integer在-128~127范围缓存复用,超出则新建对象;比较值须用equals()或基本类型转换;拆箱前必须判空防NPE;valueOf优于new且支持进制解析。

Java包装类看似简单,实则在面试中常被用来考察对语言底层机制和工程细节的理解。真正卡人的不是“有没有”,而是“为什么这么设计”“哪里容易出错”“怎么写出健壮代码”。核心痛点就三个:缓存陷阱、装箱拆箱的隐式行为、泛型与null处理。
Integer缓存池是高频雷区
面试官最爱问:Integer a = 127; Integer b = 127; System.out.println(a == b); 输出 true;但换成 128 就输出 false。这不是 bug,是设计——Integer.valueOf() 对 -128 到 127 范围内的值做了缓存复用(类似字符串常量池)。超出范围就会新建对象,== 比较的是引用地址,自然为 false。
- 永远用 equals() 比较两个包装类的值,别信 ==
- 需要判断是否相等时,优先转成基本类型再比(如
a.intValue() == b.intValue()),避免 null 异常 - 缓存范围可调(通过 JVM 参数
-XX:AutoBoxCacheMax=xxx),但生产环境不建议改,默认值已足够覆盖绝大多数场景
自动装箱拆箱藏着性能和空指针风险
编译器帮你写的“糖”,运行时可能咬你一口。比如 Integer i = null; int j = i; 直接抛 NullPointerException——拆箱时调用 i.intValue(),而 null 没有方法可调。
- 集合取值后直接拆箱前,务必判空:
if (list.get(0) != null) { int x = list.get(0); } - 循环中频繁装箱(如
for (int i = 0; i )会创建大量临时对象,影响 GC 压力;大数据量场景考虑用原始类型集合库(如 Eclipse Collections 或 Trove) - 方法参数或返回值用包装类,是为了表达“可为空”的语义,不是为了装箱而装箱
泛型里包装类不是可选,而是必须
Java 泛型擦除后只认引用类型,List<int></int> 编译不过。所以哪怕只是存数字,也得用 List<integer></integer>。但这带来两个现实问题:一是 null 元素合法(List 可以存 null),二是基本类型运算需拆箱。
立即学习“Java免费学习笔记(深入)”;
- 接口设计时,如果方法参数可能为 null(比如数据库查不到返回 null),就该用
Integer;如果业务上绝对不允许空,就用int+ 明确文档说明 - Stream 操作中注意 boxed/unbox:
IntStream.range(1,10).boxed().map(Integer::toString)是安全的;但stream.mapToInt(x -> x * 2)更高效,避免中间对象 - Map 的 key 用包装类时(如
Map<integer string></integer>),要清楚 key 为 null 是允许的,但会影响 hash 行为和查找逻辑
工具方法才是包装类存在的真正理由
很多人只记得装箱拆箱,却忽略包装类最实用的价值:它把一堆常用操作封装好了。比如 Integer.parseInt("123")、Integer.bitCount(15)、Integer.compare(a, b)——这些不用自己写,也不依赖第三方库。
-
parseInt有重载版本支持进制转换:Integer.parseInt("1010", 2)→ 10 -
valueOf比new Integer()更优:前者用缓存,后者一定新建对象(JDK9+ 已废弃构造器) - 判断字符串是否为有效整数,别手写正则或 try-catch,直接用
Integer.valueOf(str)并捕获NumberFormatException


















