Java 什么是NullPointerException,如何修复它?
什么是空指针异常(Java 什么是NullPointerException,如何修复它?,java,nullpointerexception,Java,Nullpointerexception,什么是空指针异常(java.lang.NullPointerException)以及是什么导致了它们 String a = null; System.out.println(a.toString()); // NullPointerException will be thrown 可以使用哪些方法/工具来确定原因,从而阻止异常导致程序过早终止?NullPointerExceptions是当您尝试使用指向内存中无位置(null)的引用时发生的异常,就好像它在引用对象一样。对空引用调用方法或尝试访
java.lang.NullPointerException
)以及是什么导致了它们
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
可以使用哪些方法/工具来确定原因,从而阻止异常导致程序过早终止?NullPointerExceptions是当您尝试使用指向内存中无位置(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
内的第一行,我将对象
referenceobj
显式设置为null
。这意味着我有一个引用,但它没有指向任何对象。之后,我尝试通过调用对象上的方法,将引用视为指向对象。这会导致NullPointerException
,因为在引用所指向的位置没有要执行的代码
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
(这是一个技术问题,但我认为值得一提:指向null的引用与指向无效内存位置的C指针不同。null指针实际上不指向任何地方,这与指向恰好无效的位置略有不同。)这就像你试图访问一个
为空的对象一样。考虑下面的例子:
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
null
指针不指向任何地方。当您取消引用指针p
时,您说“将存储在“p”中的位置的数据提供给我”。当p
是null
指针时,存储在p
中的位置是无处
,您说的是“将“无处”位置的数据提供给我”“。显然,它不能这样做,因此它会抛出一个空指针异常
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
一般来说,这是因为某些东西没有正确初始化。当您声明引用变量(即对象)时,实际上是在创建指向对象的指针。考虑下面的代码,其中声明一个原始类型的变量<代码> int <代码>:
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
int x;
x = 10;
在本例中,变量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
)。由于您还没有说要指向什么,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
s之外,您还可以检查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
,否则它不是null,可以安全地取消引用
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
或者,在某些情况下,方法的目的可能不仅仅是对传入的对象进行操作,因此可以接受null参数。在这种情况下,您需要检查null参数
private static String[] foo = new String[2];