NullPointerException
约 605 字大约 2 分钟
2025-07-15
NullPointerException
(空指针异常),俗称 NPE,是 Java 程序员最熟悉的 RuntimeException
异常之一。当对象为 null
时,调用其方法或访问其字段会抛出此异常。该异常由 JVM 抛出。
// NullPointerException 示例
public class Main {
public static void main(String[] args) {
String s = null;
System.out.println(s.toLowerCase()); // 这里会抛出 NullPointerException
}
}
虽然 Java 中没有指针的概念,但变量实际上是引用,Null Pointer
更确切地说是 Null Reference
,不过两者区别不大。
5.1 处理 NullPointerException
遇到 NullPointerException
时,应遵循的原则是:早暴露,早修复,严禁使用 catch
语句来隐藏这种编码错误。
// 错误示例: 捕获 NullPointerException
try {
transferMoney(from, to, amount);
} catch (NullPointerException e) {
// 这样会隐藏错误,导致问题难以发现和解决
}
良好的编码习惯可以显著降低 NullPointerException
的发生:
成员变量在定义时初始化:
public class Person { private String name = ""; // 使用空字符串初始化,避免默认为 null }
使用空字符串
""
而不是默认的null
可以避免很多NullPointerException
。编写业务逻辑时,用空字符串""
表示未填写比null
安全得多。返回空字符串
""
、空数组而不是null
:public String[] readLinesFromFile(String file) { if (getFileSize(file) == 0) { // 返回空数组而不是 null: return new String[0]; } ... }
这样可以避免调用方不必要的
null
值检查。使用
Optional<T>
处理可能为null
的返回值:public Optional<String> readFromFile(String file) { if (!fileExist(file)) { return Optional.empty(); } ... }
调用方必须通过
Optional.isPresent()
判断是否有结果,从而避免直接使用可能为null
的返回值。
5.2 定位 NullPointerException
如果产生了 NullPointerException
,例如调用 a.b.c.x()
时产生 NullPointerException
,原因可能是 a
、a.b
或 a.b.c
其中之一为 null
。
在 Java 14 之前,需要通过打印日志来确定哪个对象为 null
:
System.out.println(a);
System.out.println(a.b);
System.out.println(a.b.c);
从 Java 14 开始,JVM 可以给出详细的信息,指出哪个对象是 null
。例如:
public class Main {
public static void main(String[] args) {
Person p = new Person();
System.out.println(p.address.city.toLowerCase()); // 这里会抛出 NullPointerException
}
}
class Person {
String[] name = new String[2];
Address address = new Address();
}
class Address {
String city;
String street;
String zipcode;
}
可以在 NullPointerException
的详细信息中看到类似 ... because "<local1>.address.city" is null
,意思是 city
字段为 null
,这样就能快速定位问题。
要启用这种增强的 NullPointerException
详细信息,需要给 JVM 添加 -XX:+ShowCodeDetailsInExceptionMessages
参数:
java -XX:+ShowCodeDetailsInExceptionMessages Main.java