/**
* @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)
当你声明一个引用变量(即一个对象)时,你实际上是在创建一个指向对象的指针。请考虑以下代码,其中声明了原始类型为
int
的变量:在本例中,变量
x
是一个int
,Java将为您初始化它为0
。当您在第二行给它赋值为10
时,您的10
值将写入x
所引用的内存位置。但是,当您试图声明引用类型时,会发生一些不同的情况。获取以下代码:
第一行声明了一个名为
num
的变量,但它实际上还不包含基元值。相反,它包含一个指针(因为类型是一个引用类型Integer
)。由于您还没有指出要指向什么,Java将其设置为null
,这意味着“我指向的是nothing”。在第二行中,
new
关键字用于实例化(或创建)类型为Integer
的对象,指针变量num
被分配给该Integer
对象。当您声明一个变量,但在尝试使用该变量的内容之前没有创建对象并分配给该变量时,就会发生
NullPointerException
(称为解引用)。所以你指的是不存在的东西。当使用
.
访问方法或字段,或使用[
索引数组时,通常会发生取消引用。如果在创建对象之前试图取消对
num
的引用,则会得到NullPointerException
。在最简单的情况下,编译器会捕捉到问题并让您知道“num may not have been initialized
”,但有时您可能会编写不直接创建对象的代码。例如,可以使用以下方法:
在这种情况下,您不是在创建对象
obj
,而是假设它是在调用doSomething()
方法之前创建的。注意,可以这样调用方法:在这种情况下,
obj
就是null
。如果该方法旨在对传入对象执行某些操作,则抛出NullPointerException
是适当的,因为这是程序员错误,程序员将需要该信息进行调试。请在异常消息中包含对象变量的名称,如或者,在某些情况下,方法的目的不仅仅是操作传入的对象,因此可以接受空参数。在这种情况下,您需要检查一个空参数并以不同的方式操作。您还应该在文档中对此进行解释。例如,
doSomething()
可以写成:最后,How to pinpoint the exception & cause using Stack Trace
带有findbugs的声纳可以检测NPE。 Can sonar catch null pointer exceptions caused by JVM Dynamically
什么是NullPointerException?
一个好的开始是JavaDocs。他们包括:
如果试图对
synchronized
使用空引用,也会引发此异常,per the JLS:我该怎么修?
所以你有一个
NullPointerException
。你怎么修的?举个简单的例子,抛出一个NullPointerException
:识别空值
第一步是准确识别导致异常的值。为此,我们需要进行一些调试。学习阅读stacktrace是很重要的。这将显示引发异常的位置:
这里,我们看到在第13行(在
printString
方法中)抛出了异常。查看行并检查哪些值为空 添加日志语句或使用调试器。我们发现s
为空,对其调用length
方法会引发异常。我们可以看到,当s.length()
从方法中移除时,程序停止抛出异常。跟踪这些值的来源
下一步检查该值的来源。通过跟踪方法的调用方,我们可以看到
s
在print()
方法中与printString(name)
一起传入,并且this.name
为空。跟踪应设置这些值的位置
this.name
集合在哪里?在setName(String)
方法中。通过更多的调试,我们可以看到这个方法根本没有被调用。如果调用了方法,请确保检查调用这些方法的顺序,并且在打印方法之后不调用set方法。这足以给我们一个解决方案:在调用
printer.print()
之前添加对printer.setName()
的调用。其他修复
变量可以有一个默认值(并且
setName
可以防止将其设置为空):print
或printString
方法都可以检查null,例如:或者可以设计类,使
name
始终具有非空值:另请参见:
我还是找不到问题
如果您试图调试问题,但仍然没有解决方案,您可以发布一个问题以获得更多帮助,但请确保包括您迄今为止所做的尝试。至少,在问题中包含stacktrace,并在代码中标记重要行号。另外,请先尝试简化代码(请参见SSCCE)。
NullPointerException
是当您试图使用一个指向内存中任何位置(空)的引用时发生的异常,就像它在引用一个对象一样。对空引用调用方法或尝试访问空引用的字段将触发NullPointerException
。这些是最常见的,但是其他方式列在^{可能我能想到的最快的示例代码是:
在
main
内的第一行,我显式地将Object
引用obj
设置为null
。这意味着我有一个引用,但它没有指向任何对象。之后,我试图通过调用对象上的方法来将引用视为指向该对象。这将导致一个NullPointerException
,因为在引用所指向的位置没有要执行的代码。(这是一个技术性问题,但我认为值得一提:指向null的引用与指向无效内存位置的C指针不同。空指针实际上不指向任何地方,这与指向碰巧无效的位置有细微的不同。)
相关问题 更多 >
编程相关推荐