JAVA最常见的装箱/拆箱坑

JAVA最常见的装箱/拆箱坑

1. Integer / Long 判等用 ==

java 复制代码
Integer a = 128;
Integer b = 128;
System.out.println(a == b); // false

很多人以为是 true,但这是比较"对象地址",不是比较值。

正确写法:

java 复制代码
Objects.equals(a, b)

或者:

java 复制代码
a.equals(b)

但 a.equals(b) 要注意 a 不能为 null,所以更稳的是:

java 复制代码
Objects.equals(a, b)

这个坑在 Long id、Integer status 上特别常见。

2. 包装类型和基本类型比较触发拆箱,null 会空指针

java 复制代码
Integer status = null;

if (status == 1) {
    ...
}

这会报 NullPointerException。 因为它会自动拆箱成:

java 复制代码
status.intValue() == 1

更安全的写法:

java 复制代码
Integer.valueOf(1).equals(status)

或者:

java 复制代码
Objects.equals(status, 1)

3. Boolean 当成 boolean 用,null 会炸

java 复制代码
Boolean deleted = null;

if (deleted) {
    ...
}

这也会空指针。因为 Java 会自动拆箱:

java 复制代码
if (deleted.booleanValue()) {
    ...
}

安全写法:

java 复制代码
Boolean.TRUE.equals(deleted)

如果判断 false:

java 复制代码
Boolean.FALSE.equals(deleted)

这个在配置项、开关字段里特别常见。

4. 数据库字段是 Integer / Long,直接赋给基本类型

java 复制代码
Integer dbValue = null;
int value = dbValue;

这会空指针,因为这里发生了拆箱。

正确做法:

java 复制代码
int value = dbValue == null ? 0 : dbValue;

或者保持包装类型:

java 复制代码
Integer value = dbValue;

如果数据库字段允许为空,Java 实体通常就应该用包装类型,不要用基本类型。

5. 集合里必须用包装类型,不能用基本类型

这个不算坑,但很常见

java 复制代码
List<int> ids = new ArrayList<>();

这是错的,Java 泛型不能用基本类型。

只能写:

java 复制代码
List<Integer> ids = new ArrayList<>();

这里就涉及自动装箱/拆箱,比如:

java 复制代码
ids.add(1); // 自动装箱成 Integer
int x = ids.get(0); // 自动拆箱成 int

如果 ids.get(0) 返回 null,这里也可能炸。

6. 三元表达式里混用包装类型和基本类型

java 复制代码
Integer a = null;
int b = true ? a : 0;

这个也可能空指针,因为 a 会被拆箱成 int。

这种代码在"默认值处理"时很容易写出来。更稳的写法:

java 复制代码
int b = a == null ? 0 : a;

7. Stream / Lambda 里隐式拆箱

java 复制代码
List<Integer> list = Arrays.asList(1, 2, null, 4);
int sum = list.stream().mapToInt(Integer::intValue).sum();

这里如果有 null,会直接空指针。

安全一点要先过滤:

java 复制代码
int sum = list.stream()
        .filter(Objects::nonNull)
        .mapToInt(Integer::intValue)
        .sum();

8. 状态字段来自数据库,直接 switch 或运算

java 复制代码
Integer status = null;
switch (status) {
    case 1 -> ...
}

这也会因为拆箱报错。

所以状态字段如果可能为 null,先判空再处理。

项目里几个实用的建议

  1. Long、Integer、Boolean 比较值时,优先用 Objects.equals(...)
  2. 状态判断常量写左边,比如:
java 复制代码
Integer.valueOf(1).equals(status)
  1. Boolean 判断优先写:
java 复制代码
Boolean.TRUE.equals(flag)
  1. 数据库可空字段,Java 实体尽量用包装类型,不要用基本类型
  2. 只要看到 == 1、== 0、if (flag),就要想一下会不会拆箱
相关推荐
Miao1213111 分钟前
微服务 API 测试实践:海外某民宿平台如何构建模式驱动测试基础设施
java·开发语言
码事漫谈40 分钟前
告别数据孤岛与AI“水土不服”:金仓多模融合时序库如何让数据真正服务于业务
后端
IT_陈寒1 小时前
Redis的持久化配置把我坑惨了:你以为数据安全了?
前端·人工智能·后端
星栈1 小时前
Node 接口该写同步还是异步?
后端·node.js
红烧大青虫1 小时前
HarmonyOS应用开发实战:小事记 - UIAbility 的冷启动/热启动/后台启动三种场景与 launchParam 解析
后端·华为·harmonyos·鸿蒙系统
码事漫谈1 小时前
AI Token 缓存:命中省 10 倍,不命中白扔钱
后端
CRMEB系统商城1 小时前
开源自建还是SaaS订阅?算一笔3年经济账
java·大数据·开发语言·开源
65岁退休Coder1 小时前
LangChain v1.3.4 笔记 - 04 Agent 中间件
后端
keyipatience2 小时前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu
神奇小汤圆2 小时前
一个接口多个实现,Spring 怎么"适配多场景"?
后端