声明引用变量(即对象)时,实际上是在创建指向对象的指针。考虑以下代码,在其中声明原始类型int
的变量:
int x;
x = 10;
在此示例中,变量
x
是
int
,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, assumes obj is not null
obj.myMethod();
}
在这种情况下,您不是在创建对象
obj
,而是假设它是在调用
doSomething()
方法之前创建的。注意,可以这样调用方法:
doSomething(null);
在这种情况下,
obj
是
null
,语句
obj.myMethod()
将抛出
NullPointerException
。
如果该方法打算像上面的方法那样对传入的对象做某事,则应该抛出
NullPointerException
,因为这是程序员错误,并且程序员将需要该信息用于调试目的。
除了方法逻辑所引发的
NullPointerException
之外,您还可以检查方法参数中的
null
值,并通过在方法开头附近添加以下内容来显式地抛出NPE:
//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且可以安全地取消引用。
替代地,在某些情况下,该方法的目的不仅是对传入的对象进行操作,因此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
What methods/tools can be used to determine the cause so that you stop
the exception from causing the program to terminate prematurely?
具有发现错误的声纳可以检测NPE。
Can sonar catch null pointer exceptions caused by JVM Dynamically现在,Java 14添加了新的语言功能,以显示NullPointerException的根本原因。自2006年以来,该语言功能已成为SAP商业JVM的一部分。下面的2分钟阅读时间可以理解这一令人惊叹的语言功能。
https://jfeatures.com/blog/NullPointerException在Java 14中,以下是示例NullPointerException异常消息:
in thread "main" java.lang.NullPointerException: Cannot invoke "java.util.List.size()" because "list" is null