声明引用变量(即对象)时,实际上是在创建指向对象的指针。考虑下面的代码,其中声明了一个基元类型的变量 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();
}
/**
* @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
}
}
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)
4条答案
按热度按时间nzkunb0c1#
声明引用变量(即对象)时,实际上是在创建指向对象的指针。考虑下面的代码,其中声明了一个基元类型的变量
int
:在本例中,变量
x
是一个int
java会将它初始化为0
为你。当您指定10
在第二行,你的价值10
写入x
.但是,当您尝试声明引用类型时,会发生一些不同的情况。采用以下代码:
第一行声明了一个名为
num
,但它实际上还不包含基元值。相反,它包含一个指针(因为类型是Integer
是引用类型)。因为您还没有说要指向什么,所以java将其设置为null
,意思是“我没有指向任何东西”。在第二行
new
关键字用于示例化(或创建)类型的对象Integer
,以及指针变量num
分配给那个Integer
对象。这个
NullPointerException
在声明变量但未创建对象并在尝试使用变量内容(称为取消引用)之前将其赋给变量时发生。所以你指的是一些实际上并不存在的东西。解引用通常发生在使用
.
访问方法或字段,或使用[
索引数组。如果你试图取消引用
num
在创建对象之前,您会得到一个NullPointerException
. 在最简单的情况下,编译器会发现问题并让您知道”num may not have been initialized
,但有时您可能会编写不直接创建对象的代码。例如,您可能有如下方法:
在这种情况下,您不会创建对象
obj
,而是假设它是在doSomething()
方法被调用。注意,可以这样调用方法:在这种情况下,
obj
是null
,以及声明obj.myMethod()
将抛出一个NullPointerException
.如果该方法打算像上述方法那样对传入的对象执行某些操作,则抛出
NullPointerException
因为这是程序员的错误,程序员需要这些信息来进行调试。除了
NullPointerException
作为方法逻辑的结果抛出,还可以检查方法参数null
值并通过在方法开头附近添加以下内容显式抛出NPE:请注意,在错误消息中明确指出哪个对象不能是
null
. 验证这一点的好处是1)可以返回自己更清晰的错误消息,2)对于方法的其余部分,除非obj
是重新分配的,它不为空并且可以安全地取消引用。或者,在某些情况下,方法的目的不仅仅是对传入的对象进行操作,因此可以接受空参数。在这种情况下,您需要检查null参数并采取不同的行为。您还应该在文档中对此进行解释。例如,
doSomething()
可以写成:最后,如何使用堆栈跟踪来确定异常和原因
可以使用哪些方法/工具来确定原因,从而阻止异常导致程序过早终止?
声纳可以探测npe。sonar能动态捕获jvm引起的空指针异常吗
现在Java14添加了一个新的语言特性来显示nullpointerexception的根本原因。自2006年以来,该语言特性就一直是sap商业jvm的一部分。以下是2分钟的阅读,以了解这一惊人的语言功能。
https://jfeatures.com/blog/nullpointerexception
在java 14中,以下是nullpointerexception异常消息示例:
在线程“main”java.lang.nullpointerexception中:无法调用“java.util.list.size()”,因为“list”为null
lrpiutwd2#
什么是nullpointerexception?
一个好的起点是javadocs。它们包括:
当应用程序在需要对象的情况下尝试使用null时引发。其中包括:
调用空对象的示例方法。
访问或修改空对象的字段。
将null的长度视为数组。
像数组一样访问或修改null的插槽。
将null作为可丢弃的值抛出。
应用程序应该抛出此类的示例,以指示null对象的其他非法使用。
如果尝试使用空引用
synchronized
,也将引发此异常,根据jls:否则,如果表达式的值为null,则
NullPointerException
被抛出。我该怎么修?
所以你有一个
NullPointerException
. 你怎么修?让我们举一个简单的例子NullPointerException
:标识空值
第一步是准确地确定哪些值导致异常。为此,我们需要进行一些调试。学会读一本书很重要。这将显示引发异常的位置:
在这里,我们看到异常在第13行抛出(在
printString
方法)。查看该行,通过添加日志语句或使用调试器检查哪些值为null。我们发现s
为null,并调用length
方法引发异常。我们可以看到程序在s.length()
从方法中删除。追踪这些值的来源
下一步检查此值来自何处。通过跟踪方法的调用者,我们可以看到
s
与…一起传递printString(name)
在print()
方法,以及this.name
为空。跟踪应该设置这些值的位置
在哪里
this.name
设置?在setName(String)
方法。通过更多的调试,我们可以看到这个方法根本没有被调用。如果调用了该方法,请确保检查调用这些方法的顺序,并且set方法不会在print方法之后调用。这足以给我们提供一个解决方案:向
printer.setName()
打电话之前printer.print()
.其他修复程序
变量可以有一个默认值(和
setName
可以防止将其设置为null):要么
print
或者printString
方法可以检查null,例如:或者你可以设计这个类
name
始终具有非空值:另请参见:
避免“!=java中的“空”语句?
我还是找不到问题
如果您试图调试问题,但仍然没有解决方案,您可以发布一个问题以获得更多帮助,但请确保包含您迄今为止尝试的内容。至少,在问题中包含stacktrace,并在代码中标记重要的行号。另外,先尝试简化代码(参见sscce)。
ht4b089n3#
NullPointerException
当您试图使用一个指向内存中没有任何位置(null)的引用(就好像它引用了一个对象)时,会出现异常。对空引用调用方法或尝试访问空引用的字段将触发NullPointerException
. 这些是最常见的方法,但其他方法也列在NullPointerException
javadoc页面。可能是我能想出的最快的示例代码来说明
NullPointerException
可能是:在里面的第一行
main
,我正在显式设置Object
参考obj
等于null
. 这意味着我有一个引用,但它没有指向任何对象。之后,我尝试通过调用对象上的方法来将引用视为指向对象。这将导致NullPointerException
因为在引用所指向的位置没有要执行的代码。(这是一个技术问题,但我认为值得一提:指向null的引用与指向无效内存位置的c指针不同。空指针实际上不指向任何地方,这与指向恰好无效的位置有细微的区别。)
kzipqqlq4#
问题:是什么导致nullpointerexception(npe)?
您应该知道,java类型分为基本类型(
boolean
,int
等)和参考类型。java中的引用类型允许您使用特殊值null
这是java中表示“无对象”的方式。一
NullPointerException
每当程序试图使用null
好像这是一个真正的参考。例如,如果您这样写:标记为“here”的语句将尝试运行
length()
方法null
引用,这将抛出一个NullPointerException
.你可以用很多方法
null
将导致NullPointerException
. 事实上,你能做的只有null
不引起npe的有:将其赋给参考变量或从参考变量读取,
将其分配给数组元素或从数组元素中读取(前提是数组引用本身不为null!),
将其作为参数传递或作为结果返回,或者
使用
==
或者!=
操作员,或instanceof
.问题:如何阅读npe stacktrace?
假设我编译并运行上面的程序:
第一个观察:编译成功!程序中的问题不是编译错误。这是一个运行时错误(有些IDE可能会警告您的程序总是抛出异常。。。但是标准
javac
编译器不支持。)第二个观察:当我运行程序时,它会输出两行“gobbledygook”。错!!那可不是胡说八道。这是一个stacktrace。。。它提供了重要的信息