Java14中的NullPointerException与其前身有何不同?

Java14中的NullPointerException与其前身有何不同?,java,nullpointerexception,java-14,Java,Nullpointerexception,Java 14,JavaSE14引入的一个重要特性是,它与NullPointerException的可用性有关。是什么使Java SE 14中的NullPointerException比其前身更可用?JVM在程序中的某个点抛出NullPointerException,其中代码尝试取消引用null引用。在JavaSE14中,NullPointerException提供了有关程序提前终止的有用信息。JavaSE14之后,JVM在NullPointerException中用一条空的详细信息描述变量(根据源代码)。它通

JavaSE14引入的一个重要特性是,它与
NullPointerException
的可用性有关。是什么使Java SE 14中的
NullPointerException
比其前身更可用?

JVM在程序中的某个点抛出
NullPointerException
,其中代码尝试取消引用
null
引用。在JavaSE14中,
NullPointerException
提供了有关程序提前终止的有用信息。JavaSE14之后,JVM在
NullPointerException
中用一条空的详细信息描述变量(根据源代码)。它通过更清晰地将动态异常与静态程序代码关联起来,极大地提高了对程序的理解

让我们用一个例子来说明区别

import java.util.ArrayList;
import java.util.List;

class Price {
    double basePrice;
    double tax;

    public Price() {
    }

    public Price(double basePrice) {
        this.basePrice = basePrice;
    }

    public Price(double basePrice, double tax) {
        this.basePrice = basePrice;
        this.tax = tax;
    }
    // ...
}

class Product {
    String name;
    Price price;

    public Product() {
    }

    public Product(String name, Price price) {
        this.name = name;
        this.price = price;
    }
    // ...
}

class CartEntry {
    Product product;
    int quantity;

    public CartEntry() {
    }

    public CartEntry(Product product, int quantity) {
        this.product = product;
        this.quantity = quantity;
    }

    // ...
}

class Cart {
    String id;
    List<CartEntry> cartEntries;

    public Cart() {
        cartEntries = new ArrayList<>();
    }

    public Cart(String id) {
        this();
        this.id = id;
    }

    void addToCart(CartEntry entry) {
        cartEntries.add(entry);
    }
    // ...
}

public class Main {
    public static void main(String[] args) {
        Cart cart = new Cart("XYZ123");
        cart.addToCart(new CartEntry());
        System.out.println(cart.cartEntries.get(0).product.price.basePrice);
    }
}
此消息使程序员对
NullPointerException
的来源一无所知

Java SE 14以后版本的输出: JavaSE14中的
NullPointerException
还告诉我们哪个引用是
null


这是一个很大的进步

它记录在发行说明中

默认情况下,1.14版中不显示新消息:

提供了一个新选项以提供更有用的NullPointerException消息:

-XX:+ShowCodeDetailsExceptionMessages

如果设置了该选项,当遇到空指针时,JVM将分析程序以确定哪个引用为空,然后作为NullPointerException.getMessage()的一部分提供详细信息。除了异常消息外,还返回方法、文件名和行号

默认情况下,此选项被禁用。

以及动机的完整建议

最终

ShowCodeDetailsExceptionMessages标志的默认值已更改为“true”


当JVM抛出一个
NullPointerException
时,它现在添加一条详细消息,指定哪个引用为null

这使得堆栈跟踪更容易解释,并且如果程序访问源代码中同一行上的多个引用,则可以解决歧义。比如说,

person.name = student.name;
如果
person
student
null
,则引发
NullPointerException
,但在Java14之前,异常没有告诉我们它是哪一个。现在,它做到了:

java.lang.NullPointerException:无法读取字段“name”,因为“student”为空


有关此更改的更多信息,请参阅。

。与“提前终止”无关。如果你捕捉到这些信息,这些信息仍然存在。暗示异常会导致“程序提前终止”是模糊和不准确的。是的,未捕获异常会导致线程突然完成,但只有当程序是最后一个非守护进程线程时,才会终止程序。即使程序选择终止,这并不意味着缺乏成熟度。哦,对象不能为空。只能使用引用。
Exception in thread "main" java.lang.NullPointerException: Cannot read field "price" because "java.util.List.get(int).product" is null
    at Main.main(Main.java:74)
person.name = student.name;