Java 教程

Java 控制语句

面向对象编程

Java 内置类

Java 文件处理

Java 错误与异常

Java 多线程

Java 同步

Java 网络

Java 集合

Java 接口

Java 数据结构

Java 集合算法

高级 Java

Java 杂项

Java API 与框架

Java 类参考

Java 有用资源

Java - 空指针异常



在 Java 14 中,引入了一项名为“有帮助的NullPointerException”的新特性。当时它是一个预览特性,后来成为了 JDK 的标准部分。此增强背后的动机是使用更多详细信息丰富 NullPointerException,因为传统的 NullPointerException 仅提供了发生 NullPointerException 的文件名、方法和行号的详细信息。

Java 中传统的空指针异常

在 Java 14 增强 NullPointerException 之前,以下代码将显示如下所示的 NullPointerException 消息

// Create an employee without department
Employee emp = new Employee(1,"Robert",null);

// get the name of the dept
// as name is null, this code will throw a null pointer exception
String dept = emp.getDept().getName();

如果使用此代码片段运行,则将产生类似的结果:

Exception in thread "main" java.lang.NullPointerException
	at com.tutorialspoint.Tester.main(Tester.java:10)

Java 中新的信息性空指针异常

在调试过程中,这样的错误消息没有用。并且在多级嵌套的情况下,检查哪个字段为空导致问题变得更加困难。Java 14 满足了这一需求。在这种情况下,它提供了一个选项来返回如下所示的更有帮助的消息

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.tutorialspoint.Department.getName()" because the return value of "com.tutorialspoint.Employee.getDept()" is null
	at com.tutorialspoint.Tester.main(Tester.java:10)

在这里我们可以看到,打印了更多信息的消息来帮助调试 getDept() 为空导致的问题。为了在 Java 14 中启用此功能,我们必须使用以下标志运行 Java 代码。

-XX:+ShowCodeDetailsInExceptionMessages

现在在 Java 20 中,不再需要此标志。

针对空对象的帮助性 NullPointerException

在此示例中,我们展示了上面学习的概念。这是一个非常有用的功能,可以调试由空引用引起的错误。在这里,我们创建了两个类 Employee 和 Department。在 main 方法中,我们创建了 Employee 类的对象,但 department 传递为 null。然后我们尝试获取员工的部门名称,这会导致 NullPointerException。在输出中,我们可以看到由JVM引发的信息性空指针异常。

示例

package com.tutorialspoint;

import java.util.List;

public class Tester {

   public static void main(String[] args) {
      // declare an employee without department
      Employee emp = new Employee(1,"Robert",null);

      // get department name of null department will
      // throw a NullPointerException
      String dept = emp.getDept().getName();
      System.out.println(dept);
   }  
}

class Employee {
   int id;
   String name;
   Department dept;

   Employee (int id, String name, Department dept){
      this.id = id;
      this.name = name;
      this.dept = dept;
   }
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public Department getDept() {
      return dept;
   }
   public void setDept(Department dept) {
      this.dept = dept;
   }
}

class Department {
   int id;
   String name;
   List<Employee> employees;
   public int getId() {
      return id;
   }
   public void setId(int id) {
      this.id = id;
   }
   public String getName() {
      return name;
   }
   public void setName(String name) {
      this.name = name;
   }
   public List<Employee> getEmployees() {
      return employees;
   }
   public void setEmployees(List<Employee> employees) {
      this.employees = employees;
   }
}

输出

让我们编译并运行上述程序,这将产生以下结果:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "com.tutorialspoint.Department.getName()" because the return value of "com.tutorialspoint.Employee.getDept()" is null
	at com.tutorialspoint.Tester.main(Tester.java:10)

信息性 NullPointerException - 本地空变量

类似于对象引用,局部变量可以为 null。在 Java 14 中,如果使用空局部变量,则 JVM 会将变量名称打印为 <local>,如下所示

String name = null;   
System.out.println("Length: " + name.length() );

如果使用此代码片段运行,则将产生类似的结果:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "<local1>" is null
	at com.tutorialspoint.Tester.main(Tester.java:8)

为了打印局部变量的名称,我们在运行程序时必须使用以下标志。

-g

使用此标志会导致以下输出。

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "name" is null
	at com.tutorialspoint.Tester.main(Tester.java:8)

从 Java 20 开始,不再需要此标志。请参阅以下完整示例

针对空局部变量的帮助性 NullPointerException

在此示例中,我们展示了上面学习的概念来调试空局部引用。在这里,我们创建了一个名为 name 的局部变量,并且我们尝试获取空字符串变量的长度,这将导致 NullPointerException。在输出中,我们可以看到 JVM 引发的信息性空指针异常,其中包含空变量的实际名称。

示例

package com.tutorialspoint;

public class Tester {

   public static void main(String[] args) {	   
	   String name = null;
       // accessing property of null local variable
       // will cause a NullPointerException
	   System.out.println("Length: " + name.length() );
   }  
}

输出

让我们编译并运行上述程序,这将产生以下结果:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.length()" because "name" is null
	at com.tutorialspoint.Tester.main(Tester.java:8)
广告