广告位
什么是 java.lang.NullPointerException空指针异常,我该如何解决?
作者: 分类:编程技术浏览(1,576)2021-7-5

当你声明一个引用变量(即一个对象)时,你实际上是在创建一个指向一个对象的指针。考虑以下代码,您在其中声明了一个原始类型的变量int

int x;
x = 10;

在这个例子中,变量x是 an int0为你初始化它。当您10在第二行分配 的值时,您的值将10写入由 引用的内存位置x

但是,当您尝试声明引用类型时,会发生一些不同的事情。取以下代码:

Integer num;
num = new Integer(10);

第一行声明了一个名为 的变量num,但它实际上并不包含原始值。相反,它包含一个指针(因为类型是Integer引用类型)。由于您还没有说要指向什么,Java 将其设置为null,这意味着“我没有指向任何内容”。

在第二行中,new关键字用于实例化(或创建)类型为 的对象Integer,并将指针变量num分配给该Integer对象。

(NPE)在声明一个变量,但没有创建一个对象,并尝试使用该变量(所谓的内容之前赋给变量发生间接引用)。所以你指的是一些实际上并不存在的东西。

取消引用通常发生在.用于访问方法或字段,或[用于索引数组时。

如果您num 创建对象之前尝试取消引用则会得到NullPointerException. 在最琐碎的情况下,编译器会发现问题并让您知道“ num may not have been initialized,”,但有时您可能会编写不直接创建对象的代码。

例如,您可能有如下方法:

public void doSomething(SomeObject obj) {
   // Do something to obj, assumes obj is not null
   obj.myMethod();
}

在这种情况下,您不是在创建 object obj,而是假设它是在doSomething()调用方法之前创建的。请注意,可以像这样调用该方法:

doSomething(null);

在这种情况下,objis null,并且该语句obj.myMethod()将抛出一个NullPointerException

如果该方法旨在像上述方法那样对传入的对象执行某些操作,则抛出 是合适的,NullPointerException因为这是程序员错误,程序员将需要该信息进行调试。

除了NullPointerException作为方法逻辑的结果抛出 s之外,您还可以检查方法参数的null值并通过在方法开头附近添加类似以下内容来显式抛出 NPE:

// Throws an NPE with a custom error message if obj is null
Objects.requireNonNull(obj, "obj must not be null");

请注意,在错误消息中明确说明哪个对象不能是null. 验证这一点的优点是 1) 您可以返回自己的更清晰的错误消息,2) 对于您知道的其余方法,除非obj重新分配,否则它不为 null 并且可以安全地取消引用。

或者,可能存在方法的目的不仅仅是对传入的对象进行操作的情况,因此空参数可能是可以接受的。在这种情况下,您需要检查空参数并采取不同的行为。您还应该在文档中解释这一点。例如,doSomething()可以写成:

/**
  * @param obj An optional foo for ____. May be null, in which case
  *  the result will be ____.
  */
public void doSomething(SomeObject obj) {
    if(obj == null) {
       // Do something
    } else {
       // Do something else
    }
}

最后,如何使用堆栈跟踪查明异常和原因

可以使用哪些方法/工具来确定原因,以便阻止异常导致程序过早终止?

带有发现错误的声纳可以检测 NPE。 sonar可以动态捕获JVM引起的

现在 Java 14 增加了一个新的语言特性来显示 NullPointerException 的根本原因。自 2006 年以来,此语言功能已成为 SAP 商业 JVM 的一部分。

在 Java 14 中,以下是示例 NullPointerException 异常消息:

在线程“main”中 java.lang.NullPointerException:无法调用“java.util.List.size()”,因为“list”为空

图片压缩在线工具 tools online