Java 简明教程
Java - Null Pointer Exception
在 Java 14 中,引入了一个新功能,称为 NullPointerException,它非常有用。当时这只是一个预览功能,后来成为了 JDK 的标准部分。这种增强的动机是使用更多详细信息丰富 NullPointerException,因为传统的 NullPointerException 只提供了文件名称、方法和发生 NullPointerException 的行号的详细信息。
Traditional Null Pointer Exception in 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)
New Informative Null Pointer Exception in Java
在调试过程中,此类错误消息没有用处。并且随着嵌套级别增加,检查哪个字段为 null 导致了此问题变得更加困难。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() 为 null 的问题。为了在 Java 14 中启用此功能,我们必须使用以下标志来运行 java 代码。
-XX:+ShowCodeDetailsInExceptionMessages
现在使用 Java 20,不再需要此标志。
Helpful NullPointerException for Null Objects
在这个示例中,我们展示了以上学习到的概念。它是一个很有用的特性,用于调试由 null 引用导致的问题。在这里,我们创建了两个类 Employee 和 Department。在 main 方法中,我们创建了 Employee 类的对象,但是将 department 传递为 null。然后,我们尝试获取员工的部门名称,这会产生 NullPointerException。在输出中,我们可以看到 JVM 引发的信息丰富的空指针异常。
Example
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;
}
}
Informative NullPointerException - Local Null Variable
与对象引用类似,局部 variable 可能为 null。在 Java 14 中,如果使用了 null 局部变量,那么 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 及更高版本中,不再需要此标志。请参见以下完整示例:
Helpful NullPointerException for Null Local Variable
在这个示例中,我们展示了以上学习到的概念,以调试 null 局部引用。在这里,我们创建了一个局部变量 name,并且尝试获取 null string 变量的长度,这会导致 NullPointerException。在输出中,我们可以看到 JVM 引发的带有 null 变量实际名称的信息丰富的空指针异常。