空指针异常
# 空指针异常
在所有的 RuntimeException
异常中,Java 程序员最熟悉的恐怕就是 NullPointerException
了。
# 演示
NullPointerException
即空指针异常,俗称 NPE。如果一个对象为 null
,调用其方法或访问其字段就会产生 NullPointerException
,这个异常通常是由 JVM 抛出的,例如:
public class LearnExceptionDemo6 {
public static void main(String[] args) {
String s = null;
System.out.println(s.toLowerCase());
}
}
2
3
4
5
6
运行结果:
Exception in thread "main" java.lang.NullPointerException
at LearnExceptionDemo6.main(LearnExceptionDemo6.java:4)
2
指针这个概念实际上源自 C 语言,Java 语言中并无指针。我们定义的变量实际上是引用,Null Pointer 更确切地说是 Null Reference,不过两者区别不大。
# 处理 NPE
如果遇到 NullPointerException
,我们应该如何处理?首先,必须明确,NullPointerException
是一种代码逻辑错误,遇到 NullPointerException
,遵循原则是早暴露,早修复,严禁使用 catch
来隐藏这种编码错误:
// 错误示例: 捕获NullPointerException,但不处理!
try {
transferMoney(from, to, amount);
} catch (NullPointerException e) {
}
2
3
4
5
好的编码习惯可以极大地降低 NullPointerException
的产生,例如:
例如在成员变量在定义时初始化:
private String name = "";
如果方法有返回,尽量不返回 null,而是返回空字符串 ""
、空数组
public String[] readLinesFromFile(String file) {
if (getFileSize(file) == 0) {
// 返回空数组而不是null:
return new String[0];
}
...
}
2
3
4
5
6
7
这样可以使得调用方无需检查结果是否为 null
。
# 定位 NPE
如果产生了 NullPointerException
,例如,调用 a.b.c.x()
时产生了 NullPointerException
,原因可能是:
a
是null
;a.b
是null
;a.b.c
是null
;
确定到底是哪个对象是 null
以前只能打印这样的日志:
System.out.println(a);
System.out.println(a.b);
System.out.println(a.b.c);
2
3
从 Java 14 开始,如果产生了 NullPointerException
,JVM 可以给出详细的信息告诉我们 null
对象到底是谁。我们来看例子:
public class Main {
public static void main(String[] args) {
Person p = new Person();
System.out.println(p.address.city.toLowerCase());
}
}
class Person {
String[] name = new String[2];
Address address = new Address();
}
class Address {
String city;
String street;
String zipcode;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
可以在 NullPointerException
的详细信息中看到类似 ... because "<local1>.address.city" is null
,意思是 city
字段为 null
,这样我们就能快速定位问题所在。
这种增强的 NullPointerException
详细信息是 Java 14 新增的功能,但默认是关闭的,我们可以给 JVM 添加一个 -XX:+ShowCodeDetailsInExceptionMessages
参数启用它:
java -XX:+ShowCodeDetailsInExceptionMessages Main.java
# 小结
NullPointerException
是 Java 代码常见的逻辑错误,应当早暴露,早修复;
可以启用 Java 14 的增强异常信息来查看 NullPointerException
的详细错误信息。