什么是空指针异常(java.lang.NullPointerException),是什么原因导致的?
可以使用哪些方法/工具来确定原因,从而阻止异常导致程序过早终止?
什么是空指针异常(java.lang.NullPointerException),是什么原因导致的?
可以使用哪些方法/工具来确定原因,从而阻止异常导致程序过早终止?
当前回答
当应用程序试图在需要对象的情况下使用null时,将引发空指针异常。这些包括:
调用空对象的实例方法。 访问或修改空对象的字段。 取null的长度,就好像它是一个数组一样。 访问或修改null的槽位,就像它是一个数组一样。 抛出null,就好像它是一个Throwable值。
应用程序应该抛出该类的实例,以指示null对象的其他非法使用。
参考:http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
其他回答
nullpointerexception是当您试图使用指向内存中任何位置(null)的引用时发生的异常,就好像它引用了一个对象一样。调用空引用上的方法或试图访问空引用的字段将触发NullPointerException异常。这些是最常见的方法,但是NullPointerException javadoc页面上列出了其他方法。
可能我能想出的最快的示例代码来说明NullPointerException将是:
public class Example {
public static void main(String[] args) {
Object obj = null;
obj.hashCode();
}
}
在main内部的第一行,我显式地将对象引用obj设置为null。这意味着我有一个引用,但它不指向任何对象。在此之后,我尝试通过调用对象上的方法来将引用视为指向对象。这将导致NullPointerException,因为在引用所指向的位置中没有代码要执行。
(这是一个技术细节,但我认为值得一提:指向null的引用与指向无效内存位置的C指针不同。空指针字面上不指向任何地方,这与指向一个恰好无效的位置有微妙的不同。)
这就像你试图访问一个为空的对象。考虑下面的例子:
TypeA objA;
此时,您刚刚声明了该对象,但尚未初始化或实例化。无论何时你试图访问其中的任何属性或方法,它都会抛出NullPointerException,这是有意义的。
请看下面的例子:
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
已经有很多解释来解释它是如何发生的以及如何修复它,但是您还应该遵循最佳实践来避免nullpointerexception。
参见: 一个很好的最佳实践列表
我还要补充一点,很重要的一点是,充分利用最后一个修饰语。 在Java中使用“final”修饰符
简介:
Use the final modifier to enforce good initialization. Avoid returning null in methods, for example returning empty collections when applicable. Use annotations @NotNull and @Nullable Fail fast and use asserts to avoid propagation of null objects through the whole application when they shouldn't be null. Use equals with a known object first: if("knownObject".equals(unknownObject) Prefer valueOf() over toString(). Use null safe StringUtils methods StringUtils.isEmpty(null). Use Java 8 Optional as return value in methods, Optional class provide a solution for representing optional values instead of null references.
空指针是指不指向任何地方的指针。当你对指针p进行解引用时,你说“给我存储在p中的位置的数据”。当p是一个空指针时,存储在p中的位置是无处不在的,你是在说“给我无处位置的数据”。显然,它不能这样做,所以它抛出一个空指针异常。
一般来说,这是因为某些东西没有正确地初始化。
什么是NullPointerException?
JavaDocs是一个很好的开始。他们涵盖了以下内容:
类的情况下,当应用程序试图使用null时引发 对象是必需的。这些包括: 调用空对象的实例方法。 访问或修改空对象的字段。 取null的长度,就好像它是一个数组一样。 访问或修改null的槽位,就像它是一个数组一样。 抛出null,就好像它是一个Throwable值。 应用程序应该抛出该类的实例来指示其他类 null对象的非法使用。
同样的情况是,如果你试图使用synchronized的空引用,也会抛出这个异常,根据JLS:
SynchronizedStatement: synchronized(表达式)块 否则,如果表达式的值为null,则抛出NullPointerException异常。
我该怎么解决呢?
你有一个NullPointerException。怎么解决呢?让我们看一个抛出NullPointerException的简单例子:
public class Printer {
private String name;
public void setName(String name) {
this.name = name;
}
public void print() {
printString(name);
}
private void printString(String s) {
System.out.println(s + " (" + s.length() + ")");
}
public static void main(String[] args) {
Printer printer = new Printer();
printer.print();
}
}
识别空值
第一步是准确地识别导致异常的值。为此,我们需要进行一些调试。学习阅读stacktrace是很重要的。这将显示异常被抛出的位置:
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)
在这里,我们看到异常在第13行被抛出(在printString方法中)。查看这一行并检查哪些值为空 添加日志语句或使用调试器。我们发现s为空,对它调用length方法会引发异常。我们可以看到,当s.length()从方法中移除时,程序停止抛出异常。
跟踪这些值的来源
接下来检查这个值的来源。通过跟踪该方法的调用者,我们看到s在print()方法中与printString(name)一起传入,this.name为空。
跟踪应该在哪里设置这些值
这个。name设置在哪里?在setName(String)方法中。通过更多的调试,我们可以看到这个方法根本没有被调用。如果调用了该方法,请确保检查这些方法的调用顺序,并且set方法不会在print方法之后调用。
这足以为我们提供一个解决方案:在调用printer.print()之前添加一个对printer.setName()的调用。
其他修复
变量可以有一个默认值(setName可以防止它被设置为null):
private String name = "";
print或printString方法都可以检查null,例如:
printString((name == null) ? "" : name);
或者你可以设计类,使名称总是有一个非空值:
public class Printer {
private final String name;
public Printer(String name) {
this.name = Objects.requireNonNull(name);
}
public void print() {
printString(name);
}
private void printString(String s) {
System.out.println(s + " (" + s.length() + ")");
}
public static void main(String[] args) {
Printer printer = new Printer("123");
printer.print();
}
}
参见:
避免”!= null "语句在Java?
我还是找不到问题
如果您尝试调试问题,但仍然没有解决方案,您可以发布一个问题以获得更多帮助,但请确保包括到目前为止您所尝试的内容。至少,在问题中包含堆栈跟踪,并在代码中标记重要的行号。另外,首先试着简化代码(参见SSCCE)。