什么是 NullPointerException,如何修复它?

2024-04-27

什么是空指针异常(java.lang.NullPointerException)以及是什么导致了它们?

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


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

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

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

考虑以下代码,其中声明了一个变量原始 type int并且不初始化它:

int x;
int y = x + x;

这两行将使程序崩溃,因为没有指定值x我们正在尝试使用x指定的值y。所有基元在被操作之前都必须初始化为可用值。

现在事情变得有趣了。参考变量可以设置为null意思是 ”我正在参考nothing”。你可以获得一个null如果您以这种方式显式设置引用变量中的值,或者引用变量未初始化并且编译器不会捕获它(Java 会自动将该变量设置为null).

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

The NullPointerException(NPE) 通常发生在您声明一个变量但在尝试使用该变量的内容之前没有创建对象并将其分配给该变量时。所以你引用了一些实际上并不存在的东西。

采取以下代码:

Integer num;
num = new Integer(10);

第一行声明一个变量,名为num,但实际上还不包含参考价值。由于您还没有说出要指向什么,Java 将其设置为null.

在第二行中,new关键字用于实例化(或创建)类型的对象Integer,和参考变量num被分配给那个Integer object.

如果您尝试取消引用num before创建你得到的对象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 is null,以及声明obj.myMethod()会抛出一个NullPointerException.

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

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

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

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

或者,在某些情况下,该方法的目的不仅仅是对传入的对象进行操作,因此空参数可能是可接受的。在这种情况下,您需要检查空参数并表现出不同的行为。您还应该在文档中对此进行解释。例如,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
    }
}

最后,如何使用堆栈跟踪查明异常和原因 https://stackoverflow.com/q/3988788/2775450

可以使用哪些方法/工具来确定原因以便您停止 导致程序提前终止的异常?

具有 find bug 功能的声纳可以检测 NPE。sonar能否动态捕获JVM引起的空指针异常 https://stackoverflow.com/questions/20899931/can-sonar-catch-null-pointer-exceptions-caused-by-jvm-dynamically

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

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

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

导致的情况列表NullPointerException发生

以下是所有情况NullPointerExceptionJava 语言规范直接*提到的情况:

  • 访问(即获取或设置)instance空引用的字段。 (静态字段不算数!)
  • 呼叫instance空引用的方法。 (静态方法不算!)
  • throw null;
  • 访问空数组的元素。
  • 空同步 -synchronized (someNullReference) { ... }
  • 任何整数/浮点运算符都可以抛出NullPointerException如果其操作数之一是装箱空引用
  • 拆箱转换会抛出NullPointerException如果装箱值为空。
  • Calling super在空引用上抛出NullPointerException。如果您感到困惑,这是在谈论合格的超类构造函数调用:
class Outer {
    class Inner {}
}
class ChildOfInner extends Outer.Inner {
    ChildOfInner(Outer o) { 
        o.super(); // if o is null, NPE gets thrown
    }
}
  • Using a for (element : iterable)循环遍历空集合/数组。

  • switch (foo) { ... }(无论是表达式还是语句)可以抛出NullPointerException when foo一片空白。

  • foo.new SomeInnerClass()抛出一个NullPointerException when foo一片空白。

  • 表格方法参考name1::name2 or primaryExpression::name抛出一个NullPointerException当评估时name1 or primaryExpression计算结果为空。

    JLS 的注释中说,someInstance.someStaticMethod()不会抛出 NPE,因为someStaticMethod是静态的,但是someInstance::someStaticMethod还是扔NPE吧!

* Note that the JLS probably also says a lot about NPEs indirectly.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么是 NullPointerException,如何修复它? 的相关文章

随机推荐

  • angularjs foreach循环通过依赖于先前请求的http请求

    我想循环遍历一个数组以角度执行 http jsonp 请求 但是每个请求都会略有不同 具体取决于前一个 http jsonp 请求的时间戳 我试图循环 5 个请求 每个请求都依赖于前一个请求信息 如何执行 foreach 循环来等待每个 h
  • 如何在 django 中搜索具有 url 模式的字符串?

    我想为每个创建的帐户创建一个个人资料页面 创建后 可以像这样访问用户配置文件 http example com 用户名 http example com username 但在创建之前 我应该验证该 url 是否已经可用并且未被现有 url
  • Opengraph 和 music.listen

    尝试了几次使用 music listen 动作 最终尝试创建我们自己的聆听动作和歌曲对象 一些帖子表明 music listen 以及内置于动作和对象中的歌曲目前仅可供发布合作伙伴使用 有人能告诉我这是否属实吗 如果是 我们如何成为音乐 o
  • 在Java中,在哪里放置代码以在窗口关闭时可靠地触发?

    我有几个窗口 我想在用户采取操作关闭窗口 通过标题栏中的按钮 菜单项或我提供的按钮 之后和处理窗口之前保存默认值 有些窗口我可以DISPOSE ON CLOSE 但有些窗口我需要在它们被dispose 之前提供信息 窗体窗口关闭 http
  • fullCalendar 在同一天找到其他事件?

    我需要检测同一天的其他事件 我希望能够做的是 查找 eventClass X 的事件是否与 eventClass Y 的删除事件在同一天存在 如果不存在 它会警告用户 eventClass X 不存在 否则允许用户删除该事件 这可能吗 在探
  • 非成员规则在 Prolog 中无法按预期工作

    我正在尝试在 Prolog 中创建一个迷宫程序 其目的是找到一条从迷宫起点到迷宫中心点 m 的路线 迷宫由使用四种颜色之一连接的正方形组成 蓝色 绿色 紫色或橙色 从起点到中心的路线遵循四种颜色的重复图案 我创建了以下代码 link2 A
  • 如何让 SymPy 收集偏导数?

    我一直在使用 SymPy 来扩展复杂偏微分方程的项 并希望使用 Collect 函数来收集项 然而 在处理微分变量不同的二阶 或高阶 导数时似乎存在问题 在下面的代码示例中collect expr6 有效 但是collect expr7 没
  • IOS:给@selector添加一个参数

    当我有这行代码时 UILongPressGestureRecognizer downwardGesture UILongPressGestureRecognizer alloc initWithTarget self action sele
  • 使用 iOS 7 在后台获取步骤

    我正在开发一个应用程序 我应该在其中获取我在体育活动期间所走的步数 我找到了这段代码 void countSteps UIAccelerometer sharedAccelerometer setUpdateInterval 1 0 KUP
  • PHP 中“

    默认情况下已启用从5 4 0开始 https www php net ChangeLog 5 php 5 4 0不管php ini设置
  • 如何编写虚拟机[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • c.JSON gin.H{()} 输出空对象

    我刚刚开始学习 GO lang 结合 Gin 框架 我决定编写一些简单的 api 来获取有关酒精饮料的数据 我当前的问题是 api get 方法http localhost 8080 alcohol drinks 返回空数据对象 My co
  • 不使用 PIN 的 Twitter 身份验证

    我正在尝试验证 Windows Phone 中的用户帐户 我找到了这个 C 库来完成这项工作 tweetsharp 他们的示例非常清楚 但他们使用 pin 码来验证用户身份 using TweetSharp Pass your creden
  • 从 Nipype docker 镜像 CommandNotFound 构建奇点配方

    我有以下奇点容器配方 bin bash Bootstrap docker From nipype nipype latest labels Version v1 0 post Install nano apt get update apt
  • 将不同的内容添加到 flutter moor 查询中

    我有以下颤动沼泽查询 select recipeGarnishes where tbl gt tbl postGarnish equals true get 我该如何添加distinct查询条件 更新 我想写的查询是 select DIST
  • Maven编译失败(但Eclipse下编译成功)

    在构建我的网络项目时Eclipse 一切安好 没有错误 没有警告 然而 在构建项目时Maven it failes 下面是输出形式mvn compile c Users jwa Desktop tets traffic web gt mvn
  • Azure 有害队列计数警报规则

    在之前的一个项目中 我设法设置了一个警报规则 该规则会查看有害队列消息计数 并在队列中存在某些内容时 每天一次 使用 webhook 向 slack 发出警报 我试图找到它在 Azure 中的位置 因为看起来事情已经发生了变化 如果这不是
  • 在php中生成随机字符串作为文件名[重复]

    这个问题在这里已经有答案了 我将如何创建与文件名一起使用的随机文本字符串 我正在上传照片并在完成后重命名它们 所有照片都将存储在一个目录中 因此它们的文件名必须是唯一的 有这样做的标准方法吗 有没有办法在尝试覆盖之前检查文件名是否已经存在
  • 将字符串转换为个位数并求和

    我花了几个小时尝试寻找解决方案来完成我认为很简单的任务 但我失败了 我有一个由 3 个不同字符组成的字符串 I R O 长度从 1 到 6 E g IRRROO RRORRR IIR RIRRO 每个字符代表一个数字I 1 R 2 O 3我
  • 什么是 NullPointerException,如何修复它?

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 什么是空指针异常 java lang NullPointerException 以及是什