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

This question's answers are a community effort。编辑现有答案以改善此职位。它目前不接受新的答案或互动。

什么是空指针异常(java.lang.NullPointerException),什么原因导致它们?

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

参考方案

当您声明引用变量(即对象)时,实际上是在创建指向对象的指针。考虑以下代码,在其中声明基本类型为int的变量:

int x;
x = 10;

在此示例中,变量xint,Java会为您将其初始化为0。当您在第二行为其分配10的值时,您的10值将被写入x所指的存储位置。

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

Integer num;
num = new Integer(10);

第一行声明了一个名为num的变量,但实际上它尚未包含原始值。相反,它包含一个指针(因为类型是Integer,这是引用类型)。由于您尚未说出要指向的内容,因此Java将其设置为null,表示“我什么都没指向”。

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

当您声明变量但未创建对象并在尝试使用变量的内容之前将其分配给变量(称为取消引用)时,会出现NullPointerException。因此,您指向的是实际上不存在的东西。

使用.访问方法或字段或使用[索引数组时,通常会发生解除引用。

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

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

public void doSomething(SomeObject obj) {
   //do something to obj
}

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

doSomething(null);

在这种情况下,objnull。如果该方法旨在对传入的对象做一些事情,则抛出NullPointerException是适当的,因为这是程序员的错误,程序员将需要该信息来进行调试。请在异常消息中包括对象变量的名称,例如

Objects.requireNonNull(a, "a");

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

最后,How to pinpoint the exception & cause using Stack Trace

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

带有findbug的声纳可以检测NPE。
Can sonar catch null pointer exceptions caused by JVM Dynamically

JAVA:字节码和二进制有什么区别? - java

java字节代码(已编译的语言,也称为目标代码)与机器代码(当前计算机的本机代码)之间有什么区别?我读过一些书,他们将字节码称为二进制指令,但我不知道为什么。 参考方案 字节码是独立于平台的,在Windows中运行的编译器编译的字节码仍将在linux / unix / mac中运行。机器代码是特定于平台的,如果在Windows x86中编译,则它将仅在Win…

java:继承 - java

有哪些替代继承的方法? java大神给出的解决方案 有效的Java:偏重于继承而不是继承。 (这实际上也来自“四人帮”)。他提出的理由是,如果扩展类未明确设计为继承,则继承会引起很多不正常的副作用。例如,对super.someMethod()的任何调用都可以引导您通过未知代码的意外路径。取而代之的是,持有对本来应该扩展的类的引用,然后委托给它。这是与Eric…

Java:BigInteger,如何通过OutputStream编写它 - java

我想将BigInteger写入文件。做这个的最好方式是什么。当然,我想从输入流中读取(使用程序,而不是人工)。我必须使用ObjectOutputStream还是有更好的方法?目的是使用尽可能少的字节。谢谢马丁 参考方案 Java序列化(ObjectOutputStream / ObjectInputStream)是将对象序列化为八位字节序列的一种通用方法。但…

Java-如何将此字符串转换为日期? - java

我从服务器收到此消息,我不明白T和Z的含义,2012-08-24T09:59:59Z将此字符串转换为Date对象的正确SimpleDateFormat模式是什么? java大神给出的解决方案 这是ISO 8601标准。您可以使用SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM…

Java:从类中查找项目名称 - java

仅通过类的实例,如何使用Java反射或类似方法查找项目名称?如果不是,项目名称(我真正想要的是)可以找到程序包名称吗? 参考方案 项目只是IDE使用的简单组织工具,因此项目名称不是类或JVM中包含的信息。要获取软件包,请使用Class#getPackage()。然后,可以调用Package#getName()将包作为您在代码的包声明中看到的String来获取…