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