应优先使用包装类(如Integer)而非基本类型(如int),因业务语义需表达“缺失/未设置/未知”;数据库NULL、前端缺参、泛型集合等场景必须用包装类,仅局部计算等性能敏感处才用基本类型。

实体类属性该用包装类(如 Integer)还是基本类型(如 int),关键看这个字段在业务中是否需要表达“缺失”“未设置”或“未知”的语义。不是性能优先,而是语义优先——类型选择本身就在传递业务意图。
数据库字段允许 NULL 时必须用包装类
MySQL、PostgreSQL 等主流数据库中,数值型字段常设为 NULLABLE。比如用户年龄、订单折扣率、审核通过时间等,天然存在“暂无值”的状态。如果实体类对应字段用 int age:
- MyBatis 查询该列为 NULL 时,会尝试自动拆箱,抛 NullPointerException;
- Spring JDBC 的 BeanPropertyRowMapper 同样无法将 NULL 映射到基本类型;
- 即使加了 @Nullable 注解,运行时仍会因强制赋值而失败。
换成 Integer age,null 可自然承接,后续可用 Objects.nonNull(age) 或 age != null 明确区分“年龄为 0”和“年龄未填写”。
前端传参或配置项可能不传时推荐包装类
HTTP 请求中字段缺失是常态:表单没填某项、JSON 中省略某个 key、配置中心里某个开关未设置……这些场景下:
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
- Spring MVC 绑定 int status,若 JSON 不含 "status",默认赋值为 0,极易误判为“已启用”;
- 而 Integer status 保持为 null,配合 @NotNull 或自定义校验逻辑,可精准拦截“必填但未传”;
- 配置读取如 environment.getProperty("timeout", Integer.class),返回 null 表示配置未定义,语义清晰。
泛型、集合、反射等场景只能用包装类
Java 泛型擦除机制决定了类型参数必须是引用类型:
-
List
编译直接报错,List 才合法; - Map
、Optional 、Stream 等均依赖包装类; - 反射调用方法(如 Method.invoke())、JSON 序列化(Jackson 默认把 int 字段当 0 处理)也都以对象为契约基础。
局部变量和计算逻辑优先用基本类型
包装类有装箱/拆箱开销,且需防范缓存陷阱(如 Integer == 在 -128~127 外失效)。因此:
- 方法内临时计数、循环索引、数学运算(sum += price * qty)一律用 int、long、double;
- 避免在高频循环中反复创建 new Integer(1),优先复用 Integer.valueOf();
- 比较数值相等时,统一用 .equals() 或先拆箱再比(a.intValue() == b.intValue())。
一句话总结:对外暴露的属性(POJO/DTO/VO/Entity)、可能为空的输入输出、泛型容器元素,选包装类;对内使用的中间变量、确定非空的计算过程、性能敏感路径,选基本类型。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










