在 Java 开发中,NullPointerException(空指针异常)恐怕是出现频率最高的运行时异常。它很少是思考出来的,多数是在日志里突然蹦出来。下面从几个常见场景出发,看看它通常是怎么发生的,以及如何从源头避免。
一、典型成因
1. 调用对象的方法或访问其属性
String name = getUser().getName(); // getUser() 返回 null
System.out.println(name.length()); // 抛 NullPointerException
2. 数组或集合元素为 null
String[] arr = new String[10];
arr[0].isEmpty(); // arr[0] 为 null
3. 自动拆箱(unboxing)
Integer count = null;
int size = count; // 空 Integer 拆箱为 int 时抛异常
4. 从 Map 直接取值后强转
String val = (String) map.get("key"); // key 不存在时得到 null
二、解决思路
1. 使用 Optional 让空值显性化
Java 8 引入的 Optional 能强制调用方去考虑「可能为空」的情况:
Optional<User> user = Optional.ofNullable(getUser());
String name = user.map(User::getName).orElse("未知用户");
2. 对象方法入参使用 Objects.requireNonNull
在方法入口校验参数,让异常在最早时刻以清晰的信息暴露:
public void process(User user) {
Objects.requireNonNull(user, "user 不能为 null");
// 正常业务逻辑
}
3. 防御式判断
if (user != null && user.getName() != null) {
System.out.println(user.getName());
}
注意:
&&左侧为 false 时不会再执行右侧,所以这种写法是安全的。
三、小结
- 空指针的根源是「对可能为 null 的值不做检查就使用」。
- 良好的习惯:外部数据(数据库查询、接口返回、参数)一律假设可能为 null。
- 能用
Optional/Objects.requireNonNull的地方优先使用,让空值成为显式的约定。 - 避免返回 null:定义返回空集合
Collections.emptyList()而不是null,可以消灭一大类空指针。