我们定义如下两个类:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private String userName;
private Address address;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Address {
private String province;
private String city;
}
写个测试类测试下:
public class Test {
public static void main(String[] args) {
User user = new User();
System.out.println(user.getAddress().getProvince().length());
}
}
执行报如下异常信息:
Exception in thread "main" java.lang.NullPointerException
at com.skjava.java.feature.Test.main(Test.java:6)
在这段异常信息中我们只能看出 Test.java
中的第 6
行产生了 NullPointerException
,除此之外你还能看到其他的信息吗?你知道是 user.getAddress()
为 null
还是 user.getAddress().getProvince()
为 null
?我们很难搞清楚具体是谁导致的 NullPointerException
。
在 Java 14 之前,当发生 NullPointerException
时,错误信息通常很简单,仅仅只指出了出错的行号。这会导致我们在排查复杂表达式时显得比较困难,因为无法确定是表达式中的哪一部分导致了 NullPointerException
,我们需要花费额外的时间进行调试,特别是在长链式调用或者包含多个可能为空的对象的情况下。
为了解决这个问题,Java 14 对 NullPointerException
的提示信息进行了改进,当发生 NullPointerException
时,异常信息会明确指出哪个具体的变量或者表达式部分是空的。例如,对于表达式 a.b().c().d()
, 如果 b()
返回的对象是 null
,异常信息将明确指出 b()
返回的对象为 null
。例如上面的信息:
Exception in thread "main" java.lang.NullPointerException: Cannot invoke "*****.Address.getProvince()" because the return value of "*****.User.getAddress()" is null
at com.skjava.java.feature.Test.main(Test.java:6)
他会明确告诉你 User.getAddress()
返回的对象为 null
。
这样的提示信息将会让我们能够快速准确地定位导致 NullPointerException
的具体原因,无需逐步调试或猜测,有助于快速修复问题,减少维护时间和成本。