Java 什么是NullPointerException,如何修复它?

Java 什么是NullPointerException,如何修复它?,java,nullpointerexception,Java,Nullpointerexception,什么是空指针异常java.lang.NullPointerException?是什么导致它们 String a = null; System.out.println(a.toString()); // NullPointerException will be thrown 可以使用哪些方法/工具来确定原因,从而阻止异常导致程序过早终止?NullPointerException是指当您尝试使用指向内存中无位置null的引用时发生的异常,就像它正在引用对象一样。对空引用调用方法或尝试访问空引用的字

什么是空指针异常java.lang.NullPointerException?是什么导致它们

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
可以使用哪些方法/工具来确定原因,从而阻止异常导致程序过早终止?

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

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
可能我能想出的最快的示例代码来说明NullPointerException是:

public class Example {

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

}
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
在main中的第一行,我显式地将对象引用obj设置为null。这意味着我有一个引用,但它没有指向任何对象。之后,我尝试通过调用对象上的方法,将引用视为指向对象。这会导致NullPointerException,因为在引用所指向的位置没有要执行的代码

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown

这是一个技术问题,但我认为值得一提:指向null的引用与指向无效内存位置的C指针不同。空指针实际上不指向任何地方,这与指向恰好无效的位置有细微的区别。

这就像您试图访问空对象一样。考虑下面的例子:

TypeA objA;
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
此时,您刚刚声明了这个对象,但没有初始化或实例化。无论何时尝试访问其中的任何属性或方法,它都会抛出有意义的NullPointerException

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
请参见下面的示例:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
空指针是指不指向任何地方的指针。当你解引用一个指针p时,你说给我p中存储位置的数据。当p是空指针时,存储在p中的位置不在任何地方,您的意思是在“不在任何地方”位置给我数据。显然,它不能这样做,所以它抛出一个空指针异常

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
public class School {

    Student student;

    public School() {
        try {
            student.getId();
        }
        catch(Exception e) {
            System.out.println("Null pointer exception");
        }
    }
}

一般来说,这是因为某些东西没有正确初始化。

当您声明一个引用变量(即对象)时,实际上是在创建一个指向对象的指针。考虑下面的代码,其中声明原始类型INT:< /P>的变量
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
在本例中,变量x是一个int,Java将为您将其初始化为0。当您在第二行指定值10时,您的值10将写入x所指的内存位置

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
但是,当您试图声明引用类型时,会发生一些不同的情况。以下面的代码为例:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
Integer num;
num = new Integer(10);
第一行声明了一个名为num的变量,但它实际上还不包含基元值。相反,它包含一个指针,因为类型是Integer,而Integer是引用类型。由于您还没有说要指向什么,Java将其设置为null,这意味着我没有指向任何内容

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
在第二行中,new关键字用于实例化或创建Integer类型的对象,指针变量num被分配给该Integer对象

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
当您声明一个变量,但在尝试使用名为取消引用的变量内容之前未创建对象并将其分配给该变量时,会发生NullPointerException NPE。所以你指的是一些实际上并不存在的东西

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
取消引用通常在使用时发生。访问方法或字段,或使用[对数组进行索引

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
如果在创建对象之前尝试取消对num的引用,则会出现NullPointerException。在最常见的情况下,编译器会发现问题并告诉您num可能尚未初始化,但有时您可能会编写不直接创建对象的代码

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
例如,您可能有如下方法:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
public void doSomething(SomeObject obj) {
   // Do something to obj, assumes obj is not null
   obj.myMethod();
}
在这种情况下,您不是在创建对象obj,而是假设它是在调用doSomething方法之前创建的。注意,可以这样调用该方法:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
doSomething(null);
private static String[] foo = new String[2];
在这种情况下,obj为null,语句obj.myMethod将抛出NullPointerException

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
如果该方法打算像上面的方法那样对传入对象执行某些操作,那么抛出NullPointerException是合适的,因为这是一个程序员错误,程序员需要该信息进行调试

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
除了由于方法的逻辑而引发的NullPointerException之外,您还可以检查方法参数中的null值,并通过在方法开头附近添加类似于以下内容的内容来显式引发NPE:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
// Throws an NPE with a custom error message if obj is null
Objects.requireNonNull(obj, "obj must not be null");
请注意,在错误消息中明确指出哪个对象不能为null是很有帮助的。验证这一点的好处是,1您可以返回自己更清晰的错误消息,2对于方法的其余部分,您知道,除非重新分配obj,否则它将 s不为空,可以安全地取消引用

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
或者,在某些情况下,方法的目的不仅仅是对传入的对象进行操作,因此可以接受null参数。在这种情况下,您需要检查null参数并采取不同的行为。您还应该在文档中对此进行解释。例如,doSomething可以写成:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
/**
  * @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
    }
}
最后,

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
可以使用哪些方法/工具来确定原因,以便您停止 导致程序提前终止的异常

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
带有“发现虫子”的声纳可以探测NPE。

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
现在Java14添加了一个新的语言特性来显示NullPointerException的根本原因。自2006年以来,此语言功能一直是SAP commercial JVM的一部分。以下是2分钟的阅读,以了解这一惊人的语言功能

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
在Java 14中,以下是NullPointerException异常消息示例:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
主线程中的java.lang.NullPointerException:无法调用java.util.List.size,因为列表为null

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
在您声明的所有变量中,实际上是对对象或基本体的引用,而不是对象本身

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
当您尝试执行一个对象方法时,引用会要求活动对象执行该方法。但是如果引用引用的是NULL nothing、zero、void、nada,那么就无法执行该方法。然后运行时通过抛出NullPointerException让您知道这一点

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
您的引用指向null,因此null->Pointer

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
对象位于VM内存空间中,访问它的唯一方法是使用此引用。举个例子:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
public class Some {
    private int id;
    public int getId(){
        return this.id;
    }
    public setId( int newId ) {
        this.id = newId;
    }
}
在代码的另一个地方:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
Some reference = new Some();    // Point to a new object of type Some()
Some otherReference = null;     // Initiallly this points to NULL

reference.setId( 1 );           // Execute setId method, now private var id is 1

System.out.println( reference.getId() ); // Prints 1 to the console

otherReference = reference      // Now they both point to the only object.

reference = null;               // "reference" now point to null.

// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );

// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...

这是需要知道的一件重要事情-当上面的示例中没有对对象的更多引用时,当reference和otherReference都指向null时,则该对象是不可访问的。我们无法使用它,因此该对象已准备好进行垃圾收集,在某个时刻,VM将释放该对象使用的内存并分配另一个。

在Java中,除基本类型之外的所有内容都是以类的形式出现的

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
如果要使用任何对象,则有两个阶段:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
声明 初始化 例如:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
声明:对象; 初始化:对象=新对象; 与阵列概念相同:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
声明:项目[]=新项目[5]; 初始化:项目[0]=新项目;
如果不提供初始化部分,则会出现NullPointerException。

当应用程序在需要对象的情况下尝试使用null时,会引发null指针异常。这些措施包括:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
调用空对象的实例方法。 访问或修改空对象的字段。 将null的长度视为数组。 像数组一样访问或修改null的插槽。 将null作为可丢弃的值抛出。 应用程序应该抛出此类的实例,以指示null对象的其他非法使用

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown

引用:

空指针异常是指您正在使用对象而未对其进行初始化

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
例如,下面是一个学生类,它将在我们的代码中使用它

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
public class Student {

    private int id;

    public int getId() {
        return this.id;
    }

    public setId(int newId) {
        this.id = newId;
    }
}
下面的代码为您提供了一个空指针异常

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
public class School {

    Student student;

    public School() {
        try {
            student.getId();
        }
        catch(Exception e) {
            System.out.println("Null pointer exception");
        }
    }
}
因为您使用的是student,但是您忘记了在 正确的代码如下所示:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
public class School {

    Student student;

    public School() {
        try {
            student = new Student();
            student.setId(12);
            student.getId();
        }
        catch(Exception e) {
            System.out.println("Null pointer exception");
        }
    }
}
当一个人声明一个对象数组,然后立即尝试取消引用其中的元素时,就会出现另一个NullPointerException

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}
如果比较顺序颠倒,可以避免这种特殊的NPE;即,在保证的非空对象上使用.equals

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
数组中的所有元素;对于任何类型的对象数组,这意味着所有元素都为null

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
在访问或取消引用数组中的元素之前,必须初始化它们

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}
什么是NullPointerException? 一个好的起点是。它们包括:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
当应用程序试图在 对象是必需的。这些措施包括:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
调用空对象的实例方法。 访问或修改空对象的字段。 将null的长度视为数组。 像数组一样访问或修改null的插槽。 将null作为可丢弃的值抛出。 应用程序应该抛出此类的实例以指示其他类 非法使用空对象

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
同样的情况是,如果您尝试将null引用与synchronized一起使用,也会引发此异常:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
否则,如果表达式的值为null,则抛出NullPointerException。 我怎么修理它? 所以你有一个NullPointerException。你怎么修理它?让我们举一个简单的例子,它抛出了一个Null PoExtExchange:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
识别空值

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
第一步是准确识别导致异常的值。为此,我们需要进行一些调试 我很高兴。学习阅读stacktrace很重要。这将显示引发异常的位置:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
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)
这里,我们看到在printString方法的第13行抛出了异常。查看该行并检查哪些值为空 添加日志语句或使用调试器。我们发现s为null,对其调用length方法会引发异常。我们可以看到,当从方法中删除s.length时,程序停止抛出异常

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
跟踪这些值的来源

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
下一步检查该值的来源。通过跟踪该方法的调用者,我们可以看到s在print方法中与printStringname一起传入,并且this.name为null

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
跟踪应设置这些值的位置

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
这个名字在哪里?在setNameString方法中。通过更多的调试,我们可以看到这个方法根本没有被调用。如果调用了该方法,请确保检查调用这些方法的顺序,并且在print方法之后不调用set方法

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
这足以为我们提供一个解决方案:在调用printer.print之前添加对printer.setName的调用

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
其他修复 变量可以有一个默认值,setName可以防止将其设置为null:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
private String name = "";
print或printString方法都可以检查null,例如:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
printString((name == null) ? "" : name);
或者,您可以设计类,使名称始终具有非空值:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
另见:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
我还是找不到问题 如果您试图调试问题,但仍然没有解决方案,您可以发布一个问题以获得更多帮助,但请确保包含您迄今为止尝试过的内容。至少在问题中包含stacktrace,并在代码中标记重要行号。另外,请先尝试简化代码。请参见。

问题:是什么导致NullPointerException NPE?
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
您应该知道,Java类型分为基本类型boolean、int等和引用类型。Java中的引用类型允许您使用特殊值null,这是Java表示无对象的方式

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
每当您的程序试图像使用真实引用一样使用null时,就会在运行时引发NullPointerException。例如,如果您编写以下内容:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
public class Test {
    public static void main(String[] args) {
        String foo = null;
        int length = foo.length();   // HERE
    }
}
此处标记的语句将尝试在null引用上运行length方法,这将引发NullPointerException

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
有许多方法可以使用会导致NullPointerException的null值。事实上,您可以在不导致NPE的情况下使用null的唯一方法是:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
将其分配给参考变量或从参考变量读取, 将其分配给数组元素或从数组元素读取,前提是数组引用本身为非null!, 将其作为参数传递或作为结果返回,或 使用==或!=运算符,或instanceof。 问题:我如何阅读NPE stacktrace? 假设我编译并运行上面的程序:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
$ javac Test.java 
$ java Test
Exception in thread "main" java.lang.NullPointerException
    at Test.main(Test.java:4)
$
第一个观察:编译成功!程序中的问题不是编译错误。这是一个运行时错误。某些IDE可能会警告您的程序将始终引发异常。。。但是标准的javac编译器没有

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
第二个观察:当我运行程序时,它输出两行gobbledy-gook。错误的那不是狼吞虎咽的东西。这是一个堆栈跟踪。。。它提供了重要的信息,如果您花时间仔细阅读,这些信息将帮助您跟踪代码中的错误

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
那么让我们看看它是怎么说的:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
Exception in thread "main" java.lang.NullPointerException
堆栈跟踪的第一行告诉您一些事情:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
它告诉您引发异常的Java线程的名称。对于一个只有一个线程的简单程序,它将是主线程。让我们继续。。。 它告诉您引发的异常的全名;i、 e.java.lang.NullPointerException。 如果异常具有关联的错误消息,则该消息将在异常名称后输出。NullPointerException在这方面是不寻常的,因为它很少有错误消息。 第二行是诊断NPE最重要的一行

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
at Test.main(Test.java:4)
这告诉我们一些事情:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
在Test.main中,我们使用了测试类的主要方法。 java:4给出了类的源文件名,它告诉我们发生这种情况的语句在文件的第4行。 如果您计算上面文件中的行数,第4行就是我用HERE注释标记的行

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
请注意,在一个更复杂的示例中,NPE堆栈跟踪中将有许多行。但是你可以肯定的是,第二行,第一行,会告诉你NPE的位置

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
简而言之,堆栈跟踪将明确地告诉我们程序的哪个语句抛出了NPE

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
另见:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
不完全正确。有些东西叫做嵌套异常

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
问题:如何在代码中查找NPE异常的原因? 这是最难的部分。简单的回答是对堆栈跟踪、源代码和rel提供的证据应用逻辑推理 EvantAPI文档

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
让我们先用上面的简单例子来说明。我们从堆栈跟踪告诉我们NPE发生的位置开始:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
int length = foo.length(); // HERE
那怎么可能抛出一个NPE呢

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
事实上,只有一种方法:只有当foo的值为null时,才会发生这种情况。然后我们尝试在null上运行length方法,然后。。。砰

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
但是我听到你说如果NPE被抛出到length方法调用中怎么办

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
如果发生这种情况,堆栈跟踪看起来就会不同。第一行表示异常是在java.lang.String类的某一行中抛出的,Test.java的第4行是第二行

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
那么这个空值是从哪里来的呢?在这种情况下,这是显而易见的,我们需要做什么来修复它也是显而易见的。为foo分配一个非空值

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
好的,让我们尝试一个稍微复杂一点的例子。这需要一些逻辑推理

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
现在我们有两条at线。第一个是针对这条线:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
return args[pos].length();
int length = test(foo, 1);
    
第二个是这条线:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
return args[pos].length();
int length = test(foo, 1);
    
看第一行,这怎么可能抛出一个NPE?有两种方法:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
如果bar的值为空,则bar[pos]将抛出一个NPE。 如果bar[pos]的值为null,则对其调用length将抛出NPE。 接下来,我们需要找出这些场景中的哪一个解释了实际发生的情况。我们将首先探讨第一个问题:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
酒吧从哪里来?它是test方法调用的一个参数,如果我们查看test是如何调用的,我们可以看到它来自foo静态变量。此外,我们可以清楚地看到,我们将foo初始化为非null值。这足以暂时否定这一解释。理论上,其他一些东西可能会将foo更改为null。。。但这在这里并没有发生

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
那么我们的第二个场景呢?我们可以看到pos是1,这意味着foo[1]必须为null。这可能吗

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
的确如此!这就是问题所在。当我们这样初始化时:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
doSomething(null);
private static String[] foo = new String[2];
我们为字符串[]分配两个初始化为null的元素。在那之后,我们没有改变食物的内容。。。所以foo[1]仍然是空的

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
安卓上呢? 在Android上,追踪NPE的直接原因要简单一些。异常消息通常会告诉您正在使用的null引用的编译时类型以及在抛出NPE时尝试调用的方法。这简化了查明直接原因的过程

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown

但另一方面,Android有一些常见的平台特定的NPE原因。一种非常常见的情况是getViewById意外返回null。我的建议是搜索有关意外空返回值的原因的Q&A。

已经有很多解释来解释它是如何发生的以及如何修复它的,但是您还应该遵循最佳实践来避免出现错误

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
另见:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
我想补充一点,非常重要的是,好好利用最后的修饰语。

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
总结:

String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
使用最后一个修改器强制执行良好的初始化。 避免在方法中返回null,例如在适用时返回空集合。 使用注释和 快速失败并使用断言来避免null对象在不应为null的情况下在整个应用程序中传播。 首先将equals与已知对象一起使用:ifknownObject.equalsnownobject 比起字符串,更喜欢valueOf。 使用空安全方法StringUtils.isEmptynull。 使用Java8 Optional作为方法中的返回值,Optional类提供了表示可选值而不是空引用的解决方案。
我理解你在那里写的所有东西,但这只是因为我已经编写了一段时间的代码,并且知道什么是“指针”和“引用”,什么是null。当我试图深入到这样的解释中时,我的学生们会斜视着我,因为没有足够的背景。@mmr:谢谢你的反馈,你的观点是正确的。在互联网上很难真正判断某人在哪里,在什么程度上开始解释是安全的。我将再次尝试修改它。在实践中获取NullPointerException的一种更常见的方法是在使用它之前忘记显式地将成员变量初始化为null以外的值。对于局部变量,编译器将捕获此错误,但在本例中不会。也许这会对你的答案有所帮助?@EJP我认为你的观点是正确的,所以我更新了答案,使之更清晰,并避免在回答的地方说“零分”。@StevePowell我很久以前就表示我不希望我的答案改变。请尊重原作者的意图。虽然这是一个很好的例子,但我可以问一下,它给所有其他答案都没有涵盖的问题增加了什么?在这里使用“未初始化”这个词是不合适的。您显示的示例实际上已初始化,并且已用null初始化。对于未初始化的变量,编译器会向您投诉。+1对您有好处

有一个例子,包括通过stacktrace;说明为什么阅读它对调试NPE很重要是很重要的。为什么当有人就您提到的调试错误发帖时,我们几乎总是寻找stacktrace…这是如何工作的?我研究这个话题已经有一段时间了,但什么也找不到。我相信像你这样了不起的老师能在一秒钟内教给我!非常感谢-@RuchirBaronia调试器允许您逐行遍历程序,查看调用了哪些方法以及变量是如何更改的。IDE应该有一些工具来实现这一点。例如,请参见。@RuchirBaronia您可以在stacktrace中看到的任何NullPointerException周围的方法上设置断点,并根据您期望的值检查变量的值。如果知道变量不应该为null,则可以在任何更改该值的代码周围设置断点。您还可以使用条件断点,它将在值更改时通知您。我还建议使用静态分析工具,如FINDBUGS避免此类异常的最佳方法是在您自己没有创建对象时始终检查null。如果调用方传递null,但是null不是方法的有效参数,那么将异常抛出回调用方是正确的,因为这是调用方的错误。默默地忽略无效的输入,在方法中什么也不做是非常糟糕的建议,因为它隐藏了问题。我想在这篇文章中添加一条注释,解释在使用自动装箱时,即使是对原语的赋值也会导致NPE:如果b是整数,int a=b也会抛出NPE。在某些情况下,这会使调试感到困惑。是否可以从web浏览器捕获web应用程序引发的NPE?它将显示在web浏览器的查看页面源中。是,在调用对象上的方法或尝试访问该对象可能具有的变量之前,请检查该对象是否等于null。有时,结构化代码有助于避免空指针异常。例如,当用常量字符串检查输入字符串时,应该从常量字符串开始,如下所示:如果SomeString.equalInputString{}//即使inputString为null,也不会引发异常。因此,为了确保安全,您可以做很多事情。避免代码中出现NullPointerException问题的另一种方法是使用@Nullable和@NotNull注释。以下是关于这方面的更多信息。虽然这个答案是专门针对IntelliJ IDE的,但它也适用于其他工具,正如从评论中明显看到的那样。顺便说一句,我不允许直接编辑这个答案,也许作者可以添加它?在j2ee项目中,Nullpointer异常非常常见。某些情况下引用变量的值为null。因此,您应该正确检查变量初始化。在条件语句期间,您应该始终检查标志或引用是否包含null或不包含like:-ifflag=0{ur代码使用flag}值得一提的是,一些IDE(例如Eclipse)提供了基于可定制注释(例如上面列出的@Nullable)的自动空性分析,并警告潜在错误。也可以推断和生成这样的注释,例如IntelliJ可以基于现有的代码结构来完成。首先应该做的是在使用可为null的对象之前,您应该使用if obj==null检查它是否为null。如果为null,那么您应该编写代码来处理它。IMO,在可能的情况下,最好避免在方法中返回空对象,并且在不允许空输入参数时使用注释,以便根据约定减少代码中“if obj==null”的数量并提高代码的可读性。。。在您接受这些最佳实践之前,请保持简单,我喜欢这个答案,如果您考虑正确访问一个AN的未初始化属性,请添加此选项。object@Emiliano-仅访问初始化属性不会导致NPE。如果需要更多的情况,这就是您>>要做的:1使用null作为同步块的目标,2使用null作为开关的目标,并取消对null的装箱。在实例级别对未初始化对象执行非类级别的操作将导致NullPointerException。操作需要是特定于实例的。若操作在类级别,比如在未初始化的对象上调用静态方法,那个么它不会抛出NullPointerException异常。即使是原始包装类对象也会抛出NullPointerException.1。NullPointerException是RuntimeException,这意味着将在程序运行时出现,而不是在编译时出现。!:,但是大多数IDE都可以帮助您发现这一点。2.尽量减少在赋值语句中使用关键字“null”:@tomj0101我完全不清楚你为什么要发表这样的评论。。。但对于第二点,Optional之前的模式是返回null。关键词很好。知道如何防范是至关重要的。这提供了它的一种常见情况以及缓解它的方法
一个运行时异常,不建议捕获它,但应避免它。@Shomu:我甚至建议在什么时候捕获它?调用实例的方法时经常发生NullPointerException。例如,如果声明引用但不使其指向任何实例,调用其方法时将发生NullPointerException。例如:YourClass ref=null;//或ref=另一个ref;//但是另一个ref没有指向任何实例ref.someMethod;//它将抛出NullPointerException。通常是这样解决的:在调用方法之前,确定引用是否为null。例如:如果你的裁判null{yourRef.someMethod;}或使用异常捕获:例如:try{yourRef.someMethod;}捕获NullPointerException e{//TODO}空指针是指我不同意的任何地方。空指针不指向任何地方,它们指向空值将抛出NullPointerException,若要跳过此操作,可以使用try-catch块处理。非常感谢。