2023-12-20
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://www.skjava.com/series/article/1662953266

我们定义如下两个类:

@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 的具体原因,无需逐步调试或猜测,有助于快速修复问题,减少维护时间和成本。

阅读全文