Java基本类型与包装类混合运算需防溢出和null:输入用包装类+校验注解,运算前强制升位,关键路径用Math.exact捕获溢出,包装类参与时先判空并避免隐式装箱。

Java 中基本类型与包装类混合运算时,溢出错误往往不是来自输入越界,而是发生在计算过程中的静默环绕(如 Integer.MAX_VALUE + 1 变成负数),再加上包装类引入的 null 风险和自动装箱干扰,让问题更隐蔽。关键不是“避免用包装类”,而是明确每一步的类型意图、提前升位、主动检测。
输入阶段:用包装类 + 约束注解拦截非法值
原始类型(int)无法被 Spring 的 @Min/@Max 校验,必须改用 Integer 等包装类作为参数或配置字段:
- Controller 接口参数写成
@RequestParam @Min(Integer.MIN_VALUE) @Max(Integer.MAX_VALUE) Integer id - 配置类字段声明为
Integer timeoutMs,而非int,并配合@ConfigurationProperties和@Validated - 自定义注解如
@InIntRange统一校验逻辑,避免硬编码数值,便于后续扩展到Long或Short
运算前:强制升位,避开 int 层溢出
不要等溢出发生再补救——很多错误源于先按 int 算完再转 long,此时早已错失良机:
- 加法/乘法前显式转
long:(long)a * b✅,而不是(long)(a * b)❌(后者已在 int 层溢出) - 涉及多个
int运算的中间结果(如分页 offset = page × size),直接声明为long offset,全程用long计算 - 字面量带后缀:
10000000000L明确是 long,防止编译器误判为 int 导致编译失败或隐式截断
运行时:用 Math.exact 系列方法捕获溢出
对金额、库存、索引偏移等关键路径,不允许静默错误,必须失败可感知:
立即学习“Java免费学习笔记(深入)”;
- 使用
Math.addExact(a, b)、Math.multiplyExact(a, b),溢出立即抛ArithmeticException - 不依赖 try-catch 包裹整个业务逻辑,而是在具体算式处调用,定位精准、堆栈清晰
- 若需兼容旧 JDK 或性能极端敏感,手动检查边界:
加法前判断a > 0 && b > Integer.MAX_VALUE - a;
乘法前用long预判:(long)a * b > Integer.MAX_VALUE
包装类参与运算时:防 null + 避免隐式装箱干扰
包装类本身不解决溢出,但会放大风险——null 拆箱直接 NPE,自动装箱又掩盖真实类型:
- 禁止裸拆箱:
Integer x = null; int y = x + 1;→ NPE;应先判空或用Objects.requireNonNull(x).intValue() - 循环累加、高频计数等场景,坚持用原始类型:
int sum = 0;,而非Integer sum = 0;(每次+=都触发装箱/拆箱) - 日志或监控埋点中,避免把
int包进集合再传入:log.info("data={}", Collections.singleton(count))引入无谓对象;直接log.info("count={}", count)即可


















