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

Arv*_*ash 33 java nullpointerexception java-14

Java SE 14 引入的重要特性之一是Helpful NullPointerExceptions,它与NullPointerException. 是什么让NullPointerExceptionJava SE 14 比它的前身更有用?

Arv*_*ash 71

JVMNullPointerException在程序中的代码试图取消引用引用的点处抛出一个null。Java SE 14NullPointerException提供了有关程序提前终止的有用信息。的Java SE 14起,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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Java SE 14 之前的输出:

Exception in thread "main" java.lang.NullPointerException
    at Main.main(Main.java:74)
Run Code Online (Sandbox Code Playgroud)

此消息使程序员对NullPointerException.

Java SE 14 以上的输出:

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)
Run Code Online (Sandbox Code Playgroud)

将NullPointerException在Java SE 14还告诉我们,这是参考null。

一个很大的改进!

  • “提前终止”并不相关。如果你抓住它,信息仍然存在。 (3认同)
  • 暗示异常导致“程序提前终止”是模糊且不准确的。是的,*未捕获的*异常会导致*线程*突然完成,但只有当它是最后一个存活的非守护线程时才会终止程序。即使该计划选择终止,也不意味着不成熟。 (3认同)
  • 哦,*objects* 不能为空。只有*参考*可以。 (3认同)

小智 42

它记录在发行说明中。

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

JDK 14 中的新增功能

一个新选项可用于提供更有用的 NullPointerException 消息:

-XX:+ShowCodeDetailsInExceptionMessages

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

默认情况下,此选项处于禁用状态。

以及用于激励的完整提案JEP 358。

最终

JDK 15 中的新增功能

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


mer*_*ike 8

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

这使得堆栈跟踪更易于解释,并在程序访问源代码中同一行上的多个引用时解决歧义。例如,线

person.name = student.name;
Run Code Online (Sandbox Code Playgroud)

抛出NullPointerExceptionifperson或studentis null,但在 Java 14 之前,异常并没有告诉我们它是哪个。现在,它确实:

java.lang.NullPointerException:无法读取字段“名称”,因为“学生”为空

JEP-358 中提供了有关此更改的更多信息。