为了账号安全,请及时绑定邮箱和手机立即绑定

什么是NullPointerException,我该如何解决?

什么是NullPointerException,我该如何解决?

噜噜哒 2019-07-25 16:14:40
什么是NullPointerException,我该如何解决?什么是空指针异常(java.lang.NullPointerException)以及它们的原因是什么?可以使用哪些方法/工具来确定原因,以便停止异常导致程序过早终止?
查看完整描述

3 回答

?
神不在的星期二

TA贡献1963条经验 获得超6个赞

NullPointerExceptions是当您尝试使用指向内存中没有位置的引用(null)时发生的异常,就好像它引用了一个对象一样。在空引用上调用方法或尝试访问空引用的字段将触发a NullPointerException。这些是最常见的,但NullPointerExceptionjavadoc页面上列出了其他方式。

可能是我能想出的最快的示例代码来说明NullPointerException

public class Example {

    public static void main(String[] args) {
        Object obj = null;
        obj.hashCode();
    }}

在内线的第一行main,我明确地将Object引用设置为obj等于null。这意味着我有一个引用,但它没有指向任何对象。之后,我尝试将引用视为通过调用其上的方法指向对象。这导致a NullPointerException因为没有代码在引用指向的位置执行。

(这是一个技术性问题,但我认为值得一提的是:指向null的引用与指向无效内存位置的C指针不同。空指针实际上并不指向任何位置,这与指向恰好无效的位置。)




查看完整回答
反对 回复 2019-07-26
?
jeck猫

TA贡献1909条经验 获得超7个赞

什么是NullPointerException?

一个好的起点是JavaDocs。他们有这个涵盖:

当应用程序在需要对象的情况下尝试使用null时抛出。这些包括:

  • 调用null对象的实例方法。

  • 访问或修改空对象的字段。

  • 将null的长度视为数组。

  • 访问或修改null的槽,就像它是一个数组一样。

  • 抛出null就好像它是一个Throwable值。

应用程序应抛出此类的实例以指示null对象的其他非法使用。

还有一种情况是,如果您尝试使用空引用synchronized,那么也将根据JLS抛出此异常:

SynchronizedStatement:
    synchronized ( Expression ) Block
  • 否则,如果Expression的值为null,NullPointerException则抛出a。

我如何解决它?

所以你有一个NullPointerException。你是如何解决的?让我们举一个简单的例子,它抛出NullPointerException

public class Printer {
    private String name;

    public void setName(String name) {
        this.name = name;
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer();
        printer.print();
    }}

识别空值

第一步是确切地确定导致异常的值。为此,我们需要做一些调试。学习读取堆栈跟踪很重要。这将显示抛出异常的位置:

Exception in thread "main" java.lang.NullPointerException
    at Printer.printString(Printer.java:13)
    at Printer.print(Printer.java:9)
    at Printer.main(Printer.java:19)

在这里,我们看到在第13行抛出异常(在printString方法中)。查看该行并通过添加日志记录语句或使用调试器来检查哪些值为空。我们发现它s是null,并且调用length它上面的方法会抛出异常。我们可以看到程序在s.length()从方法中删除时停止抛出异常。

跟踪这些值来自何处

接下来检查此值的来源。按照该方法的调用者,我们可以看到,s与传递printString(name)print()方法,并this.name为空。

跟踪应设置这些值的位置

在哪里this.name设置?在setName(String)方法中。通过一些更多的调试,我们可以看到根本没有调用此方法。如果调用该方法,请确保检查调用这些方法的顺序,并且在print方法之后不调用set 方法。

这足以为我们提供一个解决方案:在呼叫printer.setName()之前添加呼叫printer.print()

其他修正

该变量可以具有默认值(并且setName可以防止将其设置为null):

private String name = "";

任一printprintString方法可以检查空,例如:

printString((name == null) ? "" : name);

或者您可以设计类,以便name 始终具有非null值

public class Printer {
    private final String name;

    public Printer(String name) {
        this.name = Objects.requireNonNull(name);
    }

    public void print() {
        printString(name);
    }

    private void printString(String s) {
        System.out.println(s + " (" + s.length() + ")");
    }

    public static void main(String[] args) {
        Printer printer = new Printer("123");
        printer.print();
    }}

也可以看看:

我还是找不到问题

如果您尝试调试问题但仍然没有解决方案,可以发布问题以获得更多帮助,但请确保包含您目前为止尝试过的内容。至少要在问题中包含堆栈跟踪,并在代码中标记重要的行号。另外,请先尝试简化代码(请参阅SSCCE)。


查看完整回答
反对 回复 2019-07-26
  • 3 回答
  • 0 关注
  • 415 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信