什么是 NullPointerException,我该如何修复它?

14,297次阅读
没有评论

共计 3510 个字符,预计需要花费 9 分钟才能阅读完成。

什么是 Null Pointer Exceptions ( java.lang.NullPointerException) 以及导致它们的原因是什么?

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

文章来源地址 https://www.toymoban.com/diary/problem/261.html

Java 中有两种主要类型的变量:

  1. 原语:包含数据的变量。如果您想操作原始变量中的数据,您可以直接操作该变量。按照惯例,基本类型以小写字母开头。例如类型变量 int or char 是原语。

  2. References:包含 an 的内存地址的变量,Object 即引用 Object. 如果你想操作 Object 引用变量引用的对象,你必须取消引用它。取消引用通常需要使用. 来访问方法或字段,或者使用 [ 来索引数组。按照惯例,引用类型通常用以大写字母开头的类型表示。例如,类型变量 Object 是引用。

考虑以下代码,您在其中声明了一个原始类型的变量 int 并且不对其进行初始化:

int x;int y = x + x;

这两行会使程序崩溃,因为没有指定值

这两行会使程序崩溃,因为没有指定值 ,而我们正试图使用 x 的值来指定 y。所有原语在被操作之前都必须被初始化为一个可用的值。

现在事情变得有趣了。引用变量可以设置为 null我没有引用任何东西”。null 如果您以这种方式显式设置引用变量,或者引用变量未初始化且编译器未捕获它(Java 会自动将变量设置为 null),则可以获得引用变量中的值。

如果引用变量由您显式设置或通过 Java 自动设置为 null,并且您尝试取消引用它,您会得到一个 NullPointerException.

(NullPointerExceptionNPE) 通常发生在声明变量但未创建对象并将其分配给变量时,然后再尝试使用变量的内容。所以你引用了一些实际上不存在的东西。

采取以下代码:

Integer num;
num = new Integer(10);

第一行声明了一个名为 的变量 num,但它实际上还没有包含一个引用值。由于您尚未说明要指向什么,因此 Java 将其设置为 null.

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

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

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

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

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

doSomething(null);

在这种情况下,

在这种情况下,obj 是 null,语句 obj.myMethod()将抛出一个 NullPointerException。

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

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

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

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

或者,在某些情况下,该方法的目的不仅仅是对传入的对象进行操作,因此 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}}

最后,如何使用 Stack Trace 查明异常和原因

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

带有 find bugs 的 Sonar 可以检测 NPE。 sonar 能否动态捕获 JVM 引起的空指针异常

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

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

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

NullPointerException 导致 a 发生的情况列表

NullPointerException以下是 Java 语言规范直接 * 提到的 所有发生 a 的情况:

  • 访问(即获取或设置)空引用的 实例字段。(静态字段不算数!)

  • 调用 空引用的 实例方法。(静态方法不算!)

  • throw null;

  • 访问空数组的元素。

  • 同步空 –synchronized (someNullReference) {...}

  • NullPointerException如果其操作数之一是装箱的空引用,则 任何整数 / 浮点运算符都可以抛出 a

  • NullPointerException如果装箱值为 null,则 取消装箱转换将抛出 a。

  • 调用 super 空引用会抛出一个 NullPointerException 如果您感到困惑,这是在谈论合格的超类构造函数调用:

class Outer {class Inner {}}class ChildOfInner extends Outer.Inner {ChildOfInner(Outer o) {o.super(); // if o is null, NPE gets thrown
    }}
  • 使用 for (element : iterable) 循环遍历空集合 / 数组。

  • switch (foo) {...}(无论是表达式还是语句)可以抛出一个NullPointerExceptionwhen foois null。

  • foo.new SomeInnerClass()NullPointerException当为空时 抛出一个foo

  • 形式的方法引用name1::name2or primaryExpression::namethrows a NullPointerExceptionwhen evaluated when name1or primaryExpressionevaluates to null.

    JLS here 的一条注释说,someInstance.someStaticMethod()不会抛出 NPE,因为它 someStaticMethod 是静态的,但 someInstance::someStaticMethod 仍然会抛出 NPE!

到此这篇关于什么是 NullPointerException,我该如何修复它?的文章就介绍到这了, 更多相关内容可以在右上角搜索或继续浏览下面的相关文章,希望大家以后多多支持 TOY 模板网!

原文地址:https://www.toymoban.com/diary/problem/261.html

如若转载,请注明出处:如若内容造成侵权 / 违法违规 / 事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

    正文完
     0
    Yojack
    版权声明:本篇文章由 Yojack 于1970-01-01发表,共计3510字。
    转载说明:
    1 本网站名称:优杰开发笔记
    2 本站永久网址:https://yojack.cn
    3 本网站的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,请联系站长进行删除处理。
    4 本站一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
    5 本站所有内容均可转载及分享, 但请注明出处
    6 我们始终尊重原创作者的版权,所有文章在发布时,均尽可能注明出处与作者。
    7 站长邮箱:laylwenl@gmail.com
    评论(没有评论)