迹忆客 专注技术分享

当前位置:主页 > 学无止境 > 编程语言 > Java >

如何解决Java中的 java.lang.NullPointerException 异常

作者:迹忆客 最近更新:2023/01/08 浏览次数:

什么是 NullPointerException ?

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

int x;
x = 10;

在本例中,变量 x 是一个 int,Java 将自动将其初始化为 0。 当我们在第二行分配值 10 时,那么值 10 将写入 x 引用的内存位置。

但是,当我们尝试声明引用类型时,会发生不同的事情。 看下面的代码:

public class Exception {
    public static void main(String[] args) {
        Integer num = null;
        num = new Integer(10);
    }
}

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

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

NullPointerException (NPE) 发生在我们声明一个变量但未创建对象并将其分配给该变量之前尝试使用该变量的内容(称为取消引用)。所以我们指向的东西实际上并不存在。

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

如果我们在创建对象之前尝试取消引用 num,则会收到 NullPointerException 。在最微不足道的情况下,编译器会发现问题并让您知道“num 可能尚未初始化”,但有时我们可能会编写不直接创建对象的代码。

例如,我们可能有如下方法:

public void doSomething(SomeObject obj) {
   // 对 obj 做某些处理,假设 obj 不为空
   obj.myMethod();
}

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

doSomething(null);

在这种情况下,obj 为 null,并且语句 obj.myMethod() 将抛出 NullPointerException 异常。

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

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

// 如果 obj 为 null,则抛出带有自定义错误消息的 NullPointerExceptions
Objects.requireNonNull(obj, "obj must not be null");

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

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

/**
  * @param obj ____ 的可选 foo。 可能为空,在这种情况下结果将是 ____
  */
public void doSomething(SomeObject obj) {
    if(obj == null) {
       // Do something
    } else {
       // Do something else
    }
}

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

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

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

in thread "main" java.lang.NullPointerException: Cannot invoke "java.util.List.size()" because "list" is null

下面我们通过一个简单的完整示例来演示一下是如何报出 java.lang.NullPointerException 错误的。

public class Exception {
    public static void main(String[] args) {
        Integer num = null;
        num.hashCode();
    }
}

运行示例

运行上面的代码,将会报出如下的错误

java.lang.NullPointerException 错误

我们也可以点击上面的运行示例来在线查看效果。

在 main 方法内部的第一行,我们明确地将 Integer 引用 num 设置为 null。 这意味着我们有一个引用,但它没有指向任何对象。 之后,尝试通过调用一个方法来将引用视为指向一个对象。 这会导致 NullPointerException,因为在引用指向的位置没有要执行的代码。

转载请发邮件至 1244347461@qq.com 进行申请,经作者同意之后,转载请以链接形式注明出处

本文地址:

相关文章

在 Java 中获取文件大小

发布时间:2023/05/01 浏览次数:139 分类:Java

Java 提供了不同的方法来获取文件的字节大小。 本教程演示了在 Java 中获取文件大小的不同方法。使用 Java IO 的文件类获取文件大小 Java IO 包的 File 类提供了以字节为单位获取文件大小的功能。

Java 中的文件分隔符

发布时间:2023/05/01 浏览次数:108 分类:Java

本篇文章介绍了 Java 中的文件分隔符。Java 中的文件分隔符 文件分隔符是用来分隔目录的字符; 例如,Unix 使用 /,Windows 使用 \ 作为文件分隔符。

Java 中的文件过滤器

发布时间:2023/05/01 浏览次数:193 分类:Java

本篇文章介绍如何在 Java 中使用 FileFilter。FileFilter 用于过滤具有特定扩展名的文件。 Java内置包IO和Apache Commons IO为FileFilter提供了类和接口来进行文件过滤操作。

Java 获取 ISO 8601 格式的当前时间戳

发布时间:2023/05/01 浏览次数:132 分类:Java

本篇文章介绍了 ISO 8601 日期格式、其重要性及其在 Java 中的使用。 它还列出了一些优点来强调为什么应该使用 ISO 格式来表示日期。

在 Java 中获取数组的子集

发布时间:2023/05/01 浏览次数:142 分类:Java

本篇文章介绍了几种在 Java 中获取数组子集的方法。使用 Arrays.copyOf() 方法获取数组的子集 使用 Arrays.copyOfRange() 方法获取数组的子集

用 Java 填充二维数组

发布时间:2023/05/01 浏览次数:110 分类:Java

二维数组是基于表结构的,即行和列,填充二维数组不能通过简单的添加到数组操作来完成。 本篇文章介绍如何在 Java 中填充二维数组。

Java 中的自然排序

发布时间:2023/05/01 浏览次数:132 分类:Java

Java 中最常用的顺序是自然顺序。 本文将展示如何使用 naturalOrder() 函数对数组进行排序。

计算 Java 数组中的重复元素

发布时间:2023/05/01 浏览次数:202 分类:Java

本篇文章介绍Java计算数组中重复元素的方法。计算 Java 数组中的重复元素。我们可以创建一个程序来计算数组中的重复元素。 该数组可以是未排序的,也可以是已排序的。

Java 中 List 和 Arraylist 的区别

发布时间:2023/05/01 浏览次数:90 分类:Java

表示为单个单元的一组单个对象称为集合。 在 Java 中,Collection 是一个具有多个已定义接口和类的框架,用于将一组对象表示为一个单元。 它允许我们操纵

扫一扫阅读全部技术教程

社交账号
  • https://www.github.com/onmpw
  • qq:1244347461

最新推荐

教程更新

热门标签

扫码一下
查看教程更方便