Integer == 比较结果取决于是否在-128~127缓存范围内且为同一对象引用;equals需防null,推荐Objects.equals;自动拆箱遇null抛NPE;int用于必有值场景,Integer用于需表达“不存在”的语义。

用 == 比较两个 Integer 为什么有时 true 有时 false
因为 Integer 是对象,== 比较的是引用地址,不是值。但 Java 对 -128 到 127 范围内的整数做了缓存(IntegerCache),所以这个区间内通过 Integer.valueOf() 创建的对象可能指向同一内存地址。
- 直接写
Integer a = 100;或Integer b = Integer.valueOf(100);→ 缓存命中,a == b为true -
Integer c = new Integer(100);→ 总是新建对象,a == c为false -
Integer d = 200;和Integer e = Integer.valueOf(200);→ 超出缓存范围,d == e很可能为false(取决于是否触发缓存扩容,但标准行为不保证)
Integer.equals() 是安全的吗
绝大多数情况下是,但要注意 null 风险:如果其中一个 Integer 是 null,调用 .equals() 会抛 NullPointerException。
- 推荐写法:
Objects.equals(a, b)(JDK 7+),它内部先判空再调用equals - 避免写
a.equals(b),除非你 100% 确保a不为null - 不要用
==替代.equals()来“省事”,这是装箱陷阱最常见源头
自动拆箱时遇到 null 会怎样
会立即抛出 NullPointerException,而且堆栈信息往往不指向你写的那行赋值或运算,而是指向字节码生成的隐式 intValue() 调用位置,排查困难。
当用户要求为 Java 代码添加注释、修改注释、审查注释、整理注释格式,或要求按照代码注释规范处理 Java 文件时,使用本技能。本技能用于统一生成和维护 Java 类注释模板、按 Git 对比 release 判断版本号、补充每行代码上方中文块注释、调整注释空行规则,并保持 Java 文件 UTF-8 无 BOM 编码。典型触发场景包括:补充类注释、更新 @version、检查 @author 来源、整理行尾注释、把注释放到代码上一行、检查注释是否符合规范、构建前检查 Java 注释风格。
- 典型场景:
Integer status = getStatusFromDB(); int code = status == null ? -1 : status;→ 这里status为null时,status右侧的自动拆箱就崩了 - 正确写法:
int code = status != null ? status.intValue() : -1;或更简洁地用status != null ? status : -1(JDK 14+ 支持模式匹配前仍建议显式判空) - Map.get() 返回
Integer、JSON 解析字段为Integer、Optional.orElse(null) 后续直接参与算术运算——这些地方都容易漏掉判空
什么时候该用 int,什么时候必须用 Integer
核心判断依据只有一个:是否需要表达「不存在」这个语义。原始类型 int 永远有值(默认 0),而 Integer 可以为 null。
- 数据库映射字段允许为 NULL、API 响应中某个数值字段可选、配置项未设置时留空 → 必须用
Integer - 循环变量、数组下标、纯计算中间结果、方法参数明确要求非空 → 优先用
int,避免无谓装箱/拆箱开销 - 注意泛型容器(如
List<integer></integer>)强制使用包装类,但遍历时别在循环体内反复做==或隐式拆箱
缓存范围、null 安全、自动拆箱崩溃点——这三个地方最容易被当成“小问题”跳过,结果在线上随机报错。写的时候多花两秒想清楚语义,比事后翻日志强得多。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










