应统一用静态工厂方法(如Integer.valueOf)替代构造器,优先使用基本类型,对null显式防御,并封装高频转换逻辑。

Java 中包装类对象(如 Integer、Boolean、Long 等)本身轻量,但若使用不当,容易引发空指针、自动装箱/拆箱性能开销、缓存陷阱和语义模糊等问题,反而推高维护成本。关键不是“怎么创建”,而是“怎么约束使用方式”——通过统一规范 + 编译期/运行期防护,把问题挡在编码阶段。
用静态工厂方法替代构造器,统一入口
避免直接调用 new Integer(42) 或 new Boolean(true)。JDK 9+ 已将包装类构造器标记为 @Deprecated(forRemoval = true),且构造器不参与缓存机制,每次新建对象,破坏值语义一致性。
- 统一用
Integer.valueOf(42)、Boolean.valueOf("true")等静态工厂方法,它们复用缓存(如-128 ~ 127范围内的Integer),节省内存,也利于 == 判断(仅限缓存范围内) - 在团队代码规范中明确禁用
new Xxx(...)形式,配合 Checkstyle 或 SpotBugs 规则(如DM_NUMBER_CTOR)自动拦截
优先使用基本类型,包装类只用于必须场景
包装类存在的本质是弥补基本类型不能为 null、不能用于泛型、不能作为集合元素等限制。只要不需要这些能力,就该用 int、boolean 等原始类型。
- 方法参数/返回值:除非要表达“缺失值”(如数据库字段可能为 NULL),否则用基本类型;用
OptionalInt替代Integer表达可选数值更语义清晰 - 局部变量与计算:禁止写
Integer sum = 0;,应写int sum = 0;,避免隐式拆箱异常和无谓对象创建 - 集合中存取:确实需要 null 容忍时再用
List<integer></integer>,并确保业务逻辑显式处理 null(如用Objects.requireNonNull()或提前校验)
对 null 值做显式防御,不依赖自动拆箱
Integer i = null; int j = i; 这种写法会在运行时抛 NullPointerException,堆栈信息不直观,排查困难。维护成本高往往来自这类“看似简单却崩溃”的隐式操作。
立即学习“Java免费学习笔记(深入)”;
- 所有可能为 null 的包装类变量,在参与算术、比较、逻辑运算前,先做非空判断或提供默认值:
int value = Objects.requireNonNullElse(i, 0);或i != null ? i : 0 - 用
Objects.equals(a, b)替代a.equals(b)比较两个包装类,避免左侧为 null 时 NPE - 在 IDE 中启用“Nullability 注解”(如
@Nullable/@NonNull),配合编译器或插件(如 IntelliJ 的 nullability 检查)提前标出风险点
封装高频转换逻辑,隔离变化点
项目中常出现重复的 “字符串转数字 + 默认值 + 异常兜底” 逻辑,比如 Integer.parseInt(s, 10) 失败后返回 -1。这类代码散落在各处,一旦需求变更(如默认值改为 0,或需记录解析失败日志),就得全局搜索替换,极易遗漏。
- 提取为工具方法,例如:
Numbers.toInt(String s, int defaultValue),内部统一处理NumberFormatException和 null - 对业务强相关的转换(如订单状态码字符串转枚举),不要用
Integer.valueOf()后再 switch,而应定义专用解析器(如OrderStatus.fromCode(String code)),把转换规则集中管理 - 必要时用 record 或 sealed class 封装带约束的值对象(如
PositiveInteger),在构造时校验并拒绝非法值,让错误更早暴露
不复杂但容易忽略:包装类不是“升级版基本类型”,而是有明确职责边界的工具。管住创建入口、守住使用边界、堵住 null 漏洞、收口转换逻辑——四条线同时发力,就能把潜在维护负担压到最低。


















