什么是空指针异常,我该如何修复它?

209

什么是空指针异常(java.lang.NullPointerException)以及它的产生原因?

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

12个回答

330
Java中,你声明的所有变量实际上都是指向对象(或原始类型)的"引用",而不是对象本身。
当你尝试执行一个对象方法时,引用会请求该对象执行该方法。但是,如果引用指向NULL(无,零,空),则没有办法执行该方法。然后运行时通过抛出NullPointerException来告诉你这一点。
你的引用"指向"null,因此"Null->Pointer"。
对象存在于VM内存空间中,唯一访问它的方式是使用this引用。看下面这个例子:
public class Some {
    private int id;
    public int getId(){
        return this.id;
    }
    public setId( int newId ) {
        this.id = newId;
    }
}

另外在你的代码中的另一个位置:

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...

这是一个重要的知识点 - 当没有任何引用指向一个对象时(在上面的例子中,当 referenceotherReference 都指向 null 时),那么该对象就变得 "不可达"。我们无法再使用它,因此该对象已准备好被垃圾回收,虚拟机将释放该对象使用的内存,并分配另一个对象。


302

当一个人声明一个对象数组,然后立即尝试对其中的元素进行解引用时,会发生NullPointerException的另一个发生。

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

如果将比较顺序颠倒,即在保证非空对象的情况下使用.equals,则可以避免此特定的NPE。

数组中的所有元素都会被初始化为其共同的初始值;对于任何类型的对象数组,这意味着所有元素都是null

在访问或解除引用数组元素之前,必须先对数组元素进行初始化。

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

4
在实例级别(而不是类级别)对未初始化的对象进行操作将会导致空指针异常。操作需要具体到实例。如果在类级别上进行操作,例如在未初始化的对象上调用静态方法,那么它不会抛出空指针异常。即使是基本类型的包装类对象也会抛出空指针异常。 - Shailendra Singh
5
  1. NullPointerException是RuntimeException,这意味着它会在程序运行时出现,而不是在编译时出现!:(但大多数IDE可以帮助您发现这个问题。
  2. 尽量减少在赋值语句中使用关键字“null”。 :)
- tomj0101
5
@tomj0101,我不太清楚你为什么发表了那个评论...但是针对你的第二点,Optional 之前的一种模式是返回 null。这个关键字很好用。知道如何防范它非常重要。 这里提供了其中一个常见情况以及缓解措施。 - Makoto
8
在哪一点上,我甚至暗示它应该被捕获了? - Makoto

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接