gpt4 book ai didi

What is a NullPointerException, and how do I fix it?(什么是NullPointerException,我如何修复它?)

转载 作者:bug小助手 更新时间:2023-10-25 17:04:10 35 4
gpt4 key购买 nike




What are Null Pointer Exceptions (java.lang.NullPointerException) and what causes them?

什么是空指针异常(java.lang.NullPointerException)以及导致它们的原因是什么?



What methods/tools can be used to determine the cause so that you stop the exception from causing the program to terminate prematurely?

可以使用什么方法/工具来确定原因,从而阻止异常导致程序过早终止?


更多回答
优秀答案推荐

There are two overarching types of variables in Java:

Java中有两种主要类型的变量:



  1. Primitives: variables that contain data. If you want to manipulate the data in a primitive variable you can manipulate that variable directly. By convention primitive types start with a lowercase letter. For example variables of type int or char are primitives.



  2. References: variables that contain the memory address of an Object i.e. variables that refer to an Object. If you want to manipulate the Object that a reference variable refers to you must dereference it. Dereferencing usually entails using . to access a method or field, or using [ to index an array. By convention reference types are usually denoted with a type that starts in uppercase. For example variables of type Object are references.




Consider the following code where you declare a variable of primitive type int and don't initialize it:

请考虑下面的代码,其中声明了一个基元类型为int的变量,但不对其进行初始化:


int x;
int y = x + x;

These two lines will crash the program because no value is specified for x and we are trying to use x's value to specify y. All primitives have to be initialized to a usable value before they are manipulated.

这两行将使程序崩溃,因为没有为x指定值,而我们试图使用x的值来指定y。在操作所有原语之前,必须将它们初始化为可用的值。


Now here is where things get interesting. Reference variables can be set to null which means "I am referencing nothing". You can get a null value in a reference variable if you explicitly set it that way, or a reference variable is uninitialized and the compiler does not catch it (Java will automatically set the variable to null).

现在,事情开始变得有趣起来。可以将引用变量设置为NULL,这意味着“我没有引用任何内容”。如果以这种方式显式设置引用变量,或者引用变量未初始化并且编译器不捕获它(Java会自动将变量设置为空),则可以在引用变量中获得空值。


If a reference variable is set to null either explicitly by you or through Java automatically, and you attempt to dereference it you get a NullPointerException.

如果您显式地或通过Java自动将引用变量设置为空,并且您试图取消对它的引用,则会出现NullPointerException异常。


The NullPointerException (NPE) typically occurs when you declare a variable but did not create an object and assign it to the variable before trying to use the contents of the variable. So you have a reference to something that does not actually exist.

当您声明一个变量,但在尝试使用该变量的内容之前没有创建对象并将其赋值给该变量时,通常会发生NullPointerException(NPE)。所以你引用了一些实际上并不存在的东西。


Take the following code:

采用以下代码:


Integer num;
num = new Integer(10);

The first line declares a variable named num, but it does not actually contain a reference value yet. Since you have not yet said what to point to, Java sets it to null.

第一行声明了一个名为num的变量,但它实际上还没有包含引用值。因为您还没有指定要指向什么,所以Java将其设置为空。


In the second line, the new keyword is used to instantiate (or create) an object of type Integer, and the reference variable num is assigned to that Integer object.

在第二行中,new关键字用于实例化(或创建)Integer类型的对象,并将引用变量num赋给该Integer对象。


If you attempt to dereference num before creating the object you get a NullPointerException. In the most trivial cases, the compiler will catch the problem and let you know that "num may not have been initialized," but sometimes you may write code that does not directly create the object.

如果在创建对象之前尝试取消对num的引用,则会出现NullPointerException异常。在最简单的情况下,编译器会捕获问题并告诉您“num可能尚未初始化”,但有时您可能会编写不直接创建对象的代码。


For instance, you may have a method as follows:

例如,您可能有如下方法:


public void doSomething(SomeObject obj) {
// Do something to obj, assumes obj is not null
obj.myMethod();
}

In which case, you are not creating the object obj, but rather assuming that it was created before the doSomething() method was called. Note, it is possible to call the method like this:

在这种情况下,您不是在创建对象obj,而是假设它是在调用DoSomething()方法之前创建的。请注意,可以这样调用该方法:


doSomething(null);

In which case, obj is null, and the statement obj.myMethod() will throw a NullPointerException.

在这种情况下,obj为空,并且语句obj.myMethod()将抛出NullPointerException。


If the method is intended to do something to the passed-in object as the above method does, it is appropriate to throw the NullPointerException because it's a programmer error and the programmer will need that information for debugging purposes.

如果该方法的目的是像上面的方法那样对传入的对象执行某些操作,则抛出NullPointerException是合适的,因为这是程序员的错误,程序员将需要该信息来进行调试。


In addition to NullPointerExceptions thrown as a result of the method's logic, you can also check the method arguments for null values and throw NPEs explicitly by adding something like the following near the beginning of a method:

除了作为方法逻辑的结果引发的NullPointerExceptions之外,您还可以检查方法参数中的空值,并通过在方法开头附近添加类似以下内容来显式抛出NPE:


// Throws an NPE with a custom error message if obj is null
Objects.requireNonNull(obj, "obj must not be null");

Note that it's helpful to say in your error message clearly which object cannot be null. The advantage of validating this is that 1) you can return your own clearer error messages and 2) for the rest of the method you know that unless obj is reassigned, it is not null and can be dereferenced safely.

请注意,在错误消息中明确说明哪个对象不能为空是很有帮助的。验证这一点的好处是1)您可以返回自己更清楚的错误消息,2)对于方法的其余部分,您知道除非重新分配obj,否则它不是空的,可以安全地解除引用。


Alternatively, there may be cases where the purpose of the method is not solely to operate on the passed in object, and therefore a null parameter may be acceptable. In this case, you would need to check for a null parameter and behave differently. You should also explain this in the documentation. For example, doSomething() could be written as:

或者,在某些情况下,该方法的目的不仅仅是对传入的对象进行操作,因此可以接受空参数。在这种情况下,您需要检查是否有空参数,并采取不同的行为。您还应该在文档中解释这一点。例如,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
}
}

Finally, 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?



Sonar with find bugs can detect NPE.
Can sonar catch null pointer exceptions caused by JVM Dynamically

带有发现窃听器的声纳可以检测到NPE。声纳能否动态捕获JVM导致的空指针异常


Now Java 14 has added a new language feature to show the root cause of NullPointerException. This language feature has been part of SAP commercial JVM since 2006.

现在,Java 14添加了一个新的语言特性来显示NullPointerException的根本原因。自2006年以来,该语言特性一直是SAP商业JVM的一部分。


In Java 14, the following is a sample NullPointerException Exception message:

在Java 14中,以下是一个示例NullPointerException异常消息:



in thread "main" java.lang.NullPointerException: Cannot invoke "java.util.List.size()" because "list" is null



List of situations that cause a NullPointerException to occur


Here are all the situations in which a NullPointerException occurs, that are directly* mentioned by the Java Language Specification:

以下是Java语言规范直接*提到的发生NullPointerException的所有情况:



  • Accessing (i.e. getting or setting) an instance field of a null reference. (static fields don't count!)

  • Calling an instance method of a null reference. (static methods don't count!)

  • throw null;

  • Accessing elements of a null array.

  • Synchronising on null - synchronized (someNullReference) { ... }

  • Any integer/floating point operator can throw a NullPointerException if one of its operands is a boxed null reference

  • An unboxing conversion throws a NullPointerException if the boxed value is null.

  • Calling super on a null reference throws a NullPointerException. If you are confused, this is talking about qualified superclass constructor invocations:


class Outer {
class Inner {}
}
class ChildOfInner extends Outer.Inner {
ChildOfInner(Outer o) {
o.super(); // if o is null, NPE gets thrown
}
}


  • Using a for (element : iterable) loop to loop through a null collection/array.

    使用for(Element:Iterable)循环遍历空集合/数组。



  • switch (foo) { ... } (whether its an expression or statement) can throw a NullPointerException when foo is null.

    当foo为空时,Switch(Foo){...}(无论它是表达式还是语句)可以抛出NullPointerException。



  • foo.new SomeInnerClass() throws a NullPointerException when foo is null.

    当foo为空时,foo.new SomeInnerClass()抛出NullPointerException。



  • Method references of the form name1::name2 or primaryExpression::name throws a NullPointerException when evaluated when name1 or primaryExpression evaluates to null.

    格式为name1::name2或premiyExpression::name的方法引用的求值结果为空时,会引发NullPointerException异常。


    a note from the JLS here says that, someInstance.someStaticMethod() doesn't throw an NPE, because someStaticMethod is static, but someInstance::someStaticMethod still throw an NPE!

    来自JLS的一条注释说,omeInstance.omeStaticMethod()不会抛出NPE,因为某些StaticMethod是静态的,但某些Instance::omeStaticMethod仍然抛出NPE!




* Note that the JLS probably also says a lot about NPEs indirectly.

*请注意,JLS可能也间接地表达了许多关于NPE的信息。



NullPointerExceptions are exceptions that occur when you try to use a reference that points to no location in memory (null) as though it were referencing an object. Calling a method on a null reference or trying to access a field of a null reference will trigger a NullPointerException. These are the most common, but other ways are listed on the NullPointerException javadoc page.

NullPointerExceptions是当您尝试使用指向内存中没有位置(空)的引用时发生的异常,就好像它在引用对象一样。对空引用调用方法或尝试访问空引用的字段将触发NullPointerException异常。这些是最常见的方法,但NullPointerException javadoc页面上还列出了其他方法。


Probably the quickest example code I could come up with to illustrate a NullPointerException would be:

可能我能想到的用来说明NullPointerException的最快的示例代码是:


public class Example {

public static void main(String[] args) {
Object obj = null;
obj.hashCode();
}

}

On the first line inside main, I'm explicitly setting the Object reference obj equal to null. This means I have a reference, but it isn't pointing to any object. After that, I try to treat the reference as though it points to an object by calling a method on it. This results in a NullPointerException because there is no code to execute in the location that the reference is pointing.

在main内的第一行,我显式地将对象引用obj设置为空。这意味着我有一个引用,但它没有指向任何对象。在此之后,我尝试通过调用对象上的方法来处理引用,就好像它指向对象一样。这会导致NullPointerException异常,因为在引用所指向的位置没有要执行的代码。


(This is a technicality, but I think it bears mentioning: A reference that points to null isn't the same as a C pointer that points to an invalid memory location. A null pointer is literally not pointing anywhere, which is subtly different than pointing to a location that happens to be invalid.)

(这是一个技术性问题,但我认为值得一提的是:指向NULL的引用与指向无效内存位置的C指针不同。空指针实际上没有指向任何地方,这与指向碰巧无效的位置略有不同。)



What is a NullPointerException?



A good place to start is the JavaDocs. They have this covered:

Java Docs是一个很好的起点。他们涵盖了这一点:




Thrown when an application attempts to use null in a case where an
object is required. These include:




  • Calling the instance method of a null object.

  • Accessing or modifying the field of a null object.

  • Taking the length of null as if it were an array.

  • Accessing or modifying the slots of null as if it were an array.

  • Throwing null as if it were a Throwable value.



Applications should throw instances of this class to indicate other
illegal uses of the null object.




It is also the case that if you attempt to use a null reference with synchronized, that will also throw this exception, per the JLS:

还有一种情况是,如果您尝试将空引用与Synchronized一起使用,也会根据JLS抛出此异常:




SynchronizedStatement:
synchronized ( Expression ) Block



  • Otherwise, if the value of the Expression is null, a NullPointerException is thrown.




How do I fix it?



So you have a NullPointerException. How do you fix it? Let's take a simple example which throws a 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();
}
}


Identify the null values

标识空值



The first step is identifying exactly which values are causing the exception. For this, we need to do some debugging. It's important to learn to read a stacktrace. This will show you where the exception was thrown:

第一步是准确识别导致异常的值。为此,我们需要进行一些调试。学习阅读堆栈跟踪很重要。这将向您显示异常抛出的位置:



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)


Here, we see that the exception is thrown on line 13 (in the printString method). Look at the line and check which values are null by
adding logging statements or using a debugger. We find out that s is null, and calling the length method on it throws the exception. We can see that the program stops throwing the exception when s.length() is removed from the method.

在这里,我们可以看到在第13行抛出了异常(在打印字符串方法中)。查看该行,并通过添加日志记录语句或使用调试器检查哪些值为空。我们发现S为空,并在其上调用长度方法抛出异常。我们可以看到,当从方法中删除s.long()时,程序停止抛出异常。



Trace where these values come from

追踪这些值的来源



Next check where this value comes from. By following the callers of the method, we see that s is passed in with printString(name) in the print() method, and this.name is null.

接下来,检查该值的来源。通过跟踪该方法的调用者,我们可以看到在print()方法中传入了S,并且这个.name为空。



Trace where these values should be set

跟踪应设置这些值的位置



Where is this.name set? In the setName(String) method. With some more debugging, we can see that this method isn't called at all. If the method was called, make sure to check the order that these methods are called, and the set method isn't called after the print method.

这个名字放在哪里?在setName(字符串)方法中。通过更多的调试,我们可以看到该方法根本没有被调用。如果调用了该方法,请确保检查这些方法的调用顺序,并且set方法不会在print方法之后调用。



This is enough to give us a solution: add a call to printer.setName() before calling printer.print().

这足以为我们提供一个解决方案:在调用printer.print()之前添加对printer.setName()的调用。



Other fixes



The variable can have a default value (and setName can prevent it being set to null):

该变量可以有一个缺省值(setName可以防止将其设置为空):



private String name = "";


Either the print or printString method can check for null, for example:

Print或printString方法都可以检查是否为空,例如:



printString((name == null) ? "" : name);


Or you can design the class so that name always has a non-null value:

或者,您可以设计类,使其名称始终具有非空值:



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();
}
}


See also:

另见:





I still can't find the problem



If you tried to debug the problem and still don't have a solution, you can post a question for more help, but make sure to include what you've tried so far. At a minimum, include the stacktrace in the question, and mark the important line numbers in the code. Also, try simplifying the code first (see SSCCE).

如果您尝试调试问题,但仍然没有解决方案,您可以发布一个问题以获得更多帮助,但请确保包含您到目前为止尝试过的内容。至少,在问题中包括堆栈跟踪,并在代码中标记重要的行号。此外,请先尝试简化代码(请参阅SSCCE)。



Question: What causes a NullPointerException (NPE)?


As you should know, Java types are divided into primitive types (boolean, int, etc.) and reference types. Reference types in Java allow you to use the special value null which is the Java way of saying "no object".

如您所知,Java类型分为基本类型(boolean、int等)。和引用类型。Java中的引用类型允许您使用特殊的空值,这是Java表示“无对象”的方式。


A NullPointerException is thrown at runtime whenever your program attempts to use a null as if it was a real reference. For example, if you write this:

每当您的程序尝试使用空值时,都会在运行时引发NullPointerException,就好像它是真正的引用一样。例如,如果您这样写:


public class Test {
public static void main(String[] args) {
String foo = null;
int length = foo.length(); // HERE
}
}

the statement labeled "HERE" is going to attempt to run the length() method on a null reference, and this will throw a NullPointerException.

标记为“HERE”的语句将尝试对空引用运行Length()方法,这将抛出NullPointerException异常。


There are many ways that you could use a null value that will result in a NullPointerException. In fact, the only things that you can do with a null without causing an NPE are:

使用空值会导致NullPointerException的方法有很多种。事实上,您可以在不导致NPE的情况下对NULL执行的唯一操作是:



  • assign it to a reference variable or read it from a reference variable,

  • assign it to an array element or read it from an array element (provided that array reference itself is non-null!),

  • pass it as a parameter or return it as a result, or

  • test it using the == or != operators, or instanceof.


Question: How do I read the NPE stacktrace?


Suppose that I compile and run the program above:

假设我编译并运行上面的程序:


$ javac Test.java 
$ java Test
Exception in thread "main" java.lang.NullPointerException
at Test.main(Test.java:4)
$

First observation: the compilation succeeds! The problem in the program is NOT a compilation error. It is a runtime error. (Some IDEs may warn your program will always throw an exception ... but the standard javac compiler doesn't.)

第一个观察:汇编成功了!程序中的问题不是编译错误。这是一个运行时错误。(某些IDE可能会警告您的程序总是会抛出异常...但标准的javac编译器没有。)


Second observation: when I run the program, it outputs two lines of "gobbledy-gook". WRONG!! That's not gobbledy-gook. It is a stacktrace ... and it provides vital information that will help you track down the error in your code if you take the time to read it carefully.

第二个观察:当我运行程序时,它输出两行“官样文章”。错了!!这不是官样文章这是一个stacktrace...它提供了重要的信息,如果你花时间仔细阅读,这些信息将帮助你找到代码中的错误。


So let's look at what it says:

那么让我们来看看它是怎么说的:


Exception in thread "main" java.lang.NullPointerException

The first line of the stack trace tells you a number of things:

堆栈跟踪的第一行告诉您许多事情:



  • It tells you the name of the Java thread in which the exception was thrown. For a simple program with one thread (like this one), it will be "main". Let's move on ...

  • It tells you the full name of the exception that was thrown; i.e. java.lang.NullPointerException.

  • If the exception has an associated error message, that will be output after the exception name. NullPointerException is unusual in this respect, because it rarely has an error message.


The second line is the most important one in diagnosing an NPE.

第二行是诊断NPE最重要的一行。


at Test.main(Test.java:4)

This tells us a number of things:

这告诉了我们许多事情:



  • "at Test.main" says that we were in the main method of the Test class.

  • "Test.java:4" gives the source filename of the class, AND it tells us that the statement where this occurred is in line 4 of the file.


If you count the lines in the file above, line 4 is the one that I labeled with the "HERE" comment.

如果计算上面文件中的行数,第4行就是我用“here”注释标记的那行。


Note that in a more complicated example, there will be lots of lines in the NPE stack trace. But you can be sure that the second line (the first "at" line) will tell you where the NPE was thrown1.

请注意,在一个更复杂的示例中,NPE堆栈跟踪中将有很多行。但可以肯定的是,第二行(第一个“at”行)将告诉您NPE被抛到了哪里。


In short, the stack trace will tell us unambiguously which statement of the program has thrown the NPE.

简而言之,堆栈跟踪将明确地告诉我们程序的哪条语句抛出了NPE。


See also: What is a stack trace, and how can I use it to debug my application errors?

另请参阅:什么是堆栈跟踪,以及如何使用它来调试应用程序错误?


1 - Not quite true. There are things called nested exceptions...

1-不完全正确。有些东西叫做嵌套异常。


Question: How do I track down the cause of the NPE exception in my code?


This is the hard part. The short answer is to apply logical inference to the evidence provided by the stack trace, the source code, and the relevant API documentation.

这是最难的部分。简短的答案是对堆栈跟踪、源代码和相关API文档提供的证据应用逻辑推理。


Let's illustrate with the simple example (above) first. We start by looking at the line that the stack trace has told us is where the NPE happened:

让我们首先用简单的例子(上面)来说明。我们从堆栈跟踪告诉我们NPE发生的位置这一行开始:


int length = foo.length(); // HERE

How can that throw an NPE?

这怎么能抛出一个NPE呢?


In fact, there is only one way: it can only happen if foo has the value null. We then try to run the length() method on null and... BANG!

事实上,只有一种方法:只有当foo的值为null时才会发生。然后我们尝试在null和.上运行length()方法。砰!


But (I hear you say) what if the NPE was thrown inside the length() method call?

但是(我听到您说)如果NPE被抛入Long()方法调用中会怎样呢?


Well, if that happened, the stack trace would look different. The first "at" line would say that the exception was thrown in some line in the java.lang.String class and line 4 of Test.java would be the second "at" line.

如果发生这种情况,堆栈跟踪将看起来不同。第一个“at”行将说明异常是在java.lang.String类的某一行中抛出的,而Test.java的第4行将是第二个“at”行。


So where did that null come from? In this case, it is obvious, and it is obvious what we need to do to fix it. (Assign a non-null value to foo.)

那么这个空值是从哪里来的呢?在这种情况下,这是显而易见的,我们需要做什么来修复它也是显而易见的。(为foo分配一个非空值。)


OK, so let's try a slightly more tricky example. This will require some logical deduction.

好的,让我们来尝试一个稍微复杂一点的例子。这将需要一些合乎逻辑的推论。


public class Test {

private static String[] foo = new String[2];

private static int test(String[] bar, int pos) {
return bar[pos].length();
}

public static void main(String[] args) {
int length = test(foo, 1);
}
}

$ javac Test.java
$ java Test
Exception in thread "main" java.lang.NullPointerException
at Test.test(Test.java:6)
at Test.main(Test.java:10)
$

So now we have two "at" lines. The first one is for this line:

所以现在我们有两个“at”行。第一个是关于这一行的:


return args[pos].length();

and the second one is for this line:

第二个是关于这条线的:


int length = test(foo, 1);


Looking at the first line, how could that throw an NPE? There are two ways:

看看第一行,这怎么能抛出NPE?有两种方法:



  • If the value of bar is null then bar[pos] will throw an NPE.

  • If the value of bar[pos] is null then calling length() on it will throw an NPE.


Next, we need to figure out which of those scenarios explains what is actually happening. We will start by exploring the first one:

下一步,我们需要弄清楚这些情景中的哪一种解释了实际发生的情况。我们将从探索第一个开始:


Where does bar come from? It is a parameter to the test method call, and if we look at how test was called, we can see that it comes from the foo static variable. In addition, we can see clearly that we initialized foo to a non-null value. That is sufficient to tentatively dismiss this explanation. (In theory, something else could change foo to null ... but that is not happening here.)

酒吧是从哪里来的?它是测试方法调用的参数,如果我们查看测试是如何调用的,我们可以看到它来自foo静态变量。此外,我们可以清楚地看到,我们将foo初始化为非空值。这足以暂时驳斥这种解释。(从理论上讲,其他东西可以将foo更改为空...但这种情况不会在这里发生。)


So what about our second scenario? Well, we can see that pos is 1, so that means that foo[1] must be null. Is this possible?

那么,我们的第二个场景呢?我们可以看到pos是1,这意味着foo[1]一定是空的。这个是可能的吗?


Indeed it is! And that is the problem. When we initialize like this:

的确如此!这就是问题所在。当我们像这样初始化时:


private static String[] foo = new String[2];

we allocate a String[] with two elements that are initialized to null. After that, we have not changed the contents of foo ... so foo[1] will still be null.

我们分配一个带有两个元素的字符串[],这两个元素被初始化为空。在那之后,我们没有改变foo的内容...因此foo[1]仍为空。


What about on Android?


On Android, tracking down the immediate cause of an NPE is a bit simpler. The exception message will typically tell you the (compile time) type of the null reference you are using and the method you were attempting to call when the NPE was thrown. This simplifies the process of pinpointing the immediate cause.

在Android上,追踪NPE的直接原因要简单一些。异常消息通常会告诉您正在使用的空引用的(编译时)类型以及在抛出NPE时尝试调用的方法。这简化了查明直接原因的过程。


But on the flipside, Android has some common platform-specific causes for NPEs. A very common is when getViewById unexpectedly returns a null. My advice would be to search for Q&As about the cause of the unexpected null return value.

但另一方面,Android有一些常见的平台特定原因导致了NPE。一种非常常见的情况是,当getViewById意外返回空值时。我的建议是搜索Q&AS以了解意外的空返回值的原因。



It's like you are trying to access an object which is null. Consider below example:

这就像您正在尝试访问一个为空的对象。请考虑以下示例:



TypeA objA;


At this time you have just declared this object but not initialized or instantiated. And whenever you try to access any property or method in it, it will throw NullPointerException which makes sense.

此时,您只声明了该对象,但尚未初始化或实例化。每当您尝试访问其中的任何属性或方法时,它都会抛出NullPointerException,这是有意义的。



See this below example as well:

也请参见下面的示例:



String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown


A null pointer exception is thrown when an application attempts to use null in a case where an object is required. These include:

当应用程序尝试在需要对象的情况下使用NULL时,会引发NULL指针异常。这些措施包括:




  1. Calling the instance method of a null object.

  2. Accessing or modifying the field of a null object.

  3. Taking the length of null as if it were an array.

  4. Accessing or modifying the slots of null as if it were an array.

  5. Throwing null as if it were a Throwable value.



Applications should throw instances of this class to indicate other illegal uses of the null object.

应用程序应该抛出此类的实例,以指示对空对象的其他非法使用。



Reference: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

参考文献:http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html



A null pointer is one that points to nowhere. When you dereference a pointer p, you say "give me the data at the location stored in "p". When p is a null pointer, the location stored in p is nowhere, you're saying "give me the data at the location 'nowhere'". Obviously, it can't do this, so it throws a null pointer exception.

空指针是指不指向任何地方的指针。当你取消对指针p的引用时,你会说“给我存储在”p“中的位置的数据。当p是空指针时,存储在p中的位置是不存在的,你说的是”给我‘无处的’位置的数据“。显然,它做不到这一点,所以它抛出了一个空指针异常。



In general, it's because something hasn't been initialized properly.

一般来说,这是因为有些东西没有正确初始化。



A lot of explanations are already present to explain how it happens and how to fix it, but you should also follow best practices to avoid NullPointerExceptions at all.

已经有很多解释来解释它是如何发生的以及如何修复它,但您还应该遵循最佳实践来完全避免NullPointerExceptions。



See also:
A good list of best practices

另请参阅:最佳实践的良好列表



I would add, very important, make a good use of the final modifier.
Using the "final" modifier whenever applicable in Java

我要补充的是,非常重要的是,要很好地利用最后一个修饰语。在Java中只要适用就使用“FINAL”修饰语



Summary:

摘要:




  1. Use the final modifier to enforce good initialization.

  2. Avoid returning null in methods, for example returning empty collections when applicable.

  3. Use annotations @NotNull and @Nullable

  4. Fail fast and use asserts to avoid propagation of null objects through the whole application when they shouldn't be null.

  5. Use equals with a known object first: if("knownObject".equals(unknownObject)

  6. Prefer valueOf() over toString().

  7. Use null safe StringUtils methods StringUtils.isEmpty(null).

  8. Use Java 8 Optional as return value in methods, Optional class provide a solution for representing optional values instead of null references.



A null pointer exception is an indicator that you are using an object without initializing it.

空指针异常是一个指示符,表示您正在使用一个对象,而没有对其进行初始化。



For example, below is a student class which will use it in our code.

例如,下面是一个学生类,它将在我们的代码中使用它。



public class Student {

private int id;

public int getId() {
return this.id;
}

public setId(int newId) {
this.id = newId;
}
}


The below code gives you a null pointer exception.

下面的代码给出了一个空指针异常。



public class School {

Student student;

public School() {
try {
student.getId();
}
catch(Exception e) {
System.out.println("Null pointer exception");
}
}
}


Because you are using student, but you forgot to initialize it like in the
correct code shown below:

因为您正在使用Student,但是您忘记了在如下所示的正确代码中对其进行初始化:



public class School {

Student student;

public School() {
try {
student = new Student();
student.setId(12);
student.getId();
}
catch(Exception e) {
System.out.println("Null pointer exception");
}
}
}


In Java, everything (excluding primitive types) is in the form of a class.

在Java中,所有的东西(不包括原始类型)都是以类的形式存在的。



If you want to use any object then you have two phases:

如果要使用任何对象,则有两个阶段:




  1. Declare

  2. Initialization



Example:

示例:




  • Declaration: Object object;

  • Initialization: object = new Object();



Same for the array concept:

阵列概念也是如此:




  • Declaration: Item item[] = new Item[5];

  • Initialization: item[0] = new Item();



If you are not giving the initialization section then the NullPointerException arise.

如果没有给出初始化节,则会出现NullPointerException异常。



In Java all the variables you declare are actually "references" to the objects (or primitives) and not the objects themselves.

在Java中,您声明的所有变量实际上都是对对象(或原语)的“引用”,而不是对象本身。



When you attempt to execute one object method, the reference asks the living object to execute that method. But if the reference is referencing NULL (nothing, zero, void, nada) then there is no way the method gets executed. Then the runtime let you know this by throwing a NullPointerException.

当您尝试执行一个对象方法时,引用会要求活动对象执行该方法。但是,如果引用引用的是NULL(Nothing、Zero、Vid、Nada),那么就不可能执行该方法。然后运行库通过抛出NullPointerException来通知您这一点。



Your reference is "pointing" to null, thus "Null -> Pointer".

您的引用是“指向”空的,因此是“空->指针”。



The object lives in the VM memory space and the only way to access it is using this references. Take this example:

该对象驻留在VM内存空间中,访问它的唯一方式是使用此引用。举个例子:



public class Some {
private int id;
public int getId(){
return this.id;
}
public setId( int newId ) {
this.id = newId;
}
}


And on another place in your code:

和代码中的另一个位置:



Some reference = new Some();    // Point to a new object of type Some()
Some otherReference = null; // Initiallly this points to NULL

reference.setId( 1 ); // Execute setId method, now private var id is 1

System.out.println( reference.getId() ); // Prints 1 to the console

otherReference = reference // Now they both point to the only object.

reference = null; // "reference" now point to null.

// But "otherReference" still point to the "real" object so this print 1 too...
System.out.println( otherReference.getId() );

// Guess what will happen
System.out.println( reference.getId() ); // :S Throws NullPointerException because "reference" is pointing to NULL remember...


This an important thing to know - when there are no more references to an object (in the example above when reference and otherReference both point to null) then the object is "unreachable". There is no way we can work with it, so this object is ready to be garbage collected, and at some point, the VM will free the memory used by this object and will allocate another.

要知道这一点很重要--当不再有对对象的引用时(在上面的例子中,当引用和其他引用都指向空时),那么该对象是“不可到达的”。我们无法使用它,因此此对象已准备好被垃圾回收,并且在某个时刻,VM将释放此对象使用的内存并分配另一个。



Another occurrence of a NullPointerException occurs when one declares an object array, then immediately tries to dereference elements inside of it.

当您声明一个对象数组,然后立即尝试取消引用其中的元素时,会发生另一种NullPointerException。



String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
System.out.println(phrase.equals(keyPhrase));
}


This particular NPE can be avoided if the comparison order is reversed; namely, use .equals on a guaranteed non-null object.

如果颠倒比较顺序,则可以避免这种特定的NPE;即,在保证的非空对象上使用.equals。



All elements inside of an array are initialized to their common initial value; for any type of object array, that means that all elements are null.

数组中的所有元素都被初始化为它们的公共初始值;对于任何类型的对象数组,这意味着所有元素都为空。



You must initialize the elements in the array before accessing or dereferencing them.

在访问或取消引用数组中的元素之前,必须先对其进行初始化。



String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
System.out.println(phrase.equals(keyPhrase));
}

更多回答

"The best way to avoid this type of exception is to always check for null when you did not create the object yourself." If the caller passes null, but null is not a valid argument for the method, then it's correct to throw the exception back at the caller because it's the caller's fault. Silently ignoring invalid input and doing nothing in the method is extremely poor advice because it hides the problem.

“避免此类异常的最佳方法是在不是您自己创建对象时始终检查是否为空。”如果调用方传递NULL,但NULL不是该方法的有效参数,则将异常抛回调用方是正确的,因为这是调用方的错误。默默地忽略无效输入并在方法中什么都不做是非常糟糕的建议,因为它隐藏了问题。

I would add a remark about this post explaining that even assignments to primitives can cause NPEs when using autoboxing: int a=b can throw an NPE if b is an Integer. There are cases where this is confusing to debug.

我想对这篇文章加上一句话,解释说在使用自动装箱时,即使是对原语的赋值也会导致NPE:如果b是整数,则int a=b可能会抛出NPE。在某些情况下,这会使调试感到困惑。

Is it possible to capture NPE thrown by a webapp from the web browser?like will it show in the view page source from the web browser..

可以从Web浏览器捕获Web应用程序抛出的NPE吗?就像它是否会显示在Web浏览器的查看页面源代码中一样。

Yes check if the object equals null before you invoke a method on it or try to access a variable it might have. Some times structuring your code can help avoid null pointer exception. eg when checking an input string with a constant string you should start with the constant string like here: if ("SomeString".equals(inputString)) {} //even if inputString is null no exception is thrown. So there are a bunch of things that you can do to try to be safe.

是,在调用对象上的方法或尝试访问它可能具有的变量之前,检查对象是否等于空。有时候,组织代码可以帮助避免空指针异常。例如,当使用常量字符串检查输入字符串时,应该从常量字符串开始,如下所示:if(“SomeString.equals(InputString)){}//即使inputString值为空,也不会抛出异常。因此,为了安全起见,你可以做很多事情。

An additional way of avoiding NullPointerException problems in your code is to use @Nullable and @NotNull annotations. The following answer has more information on this. Although this answer is specificially about the IntelliJ IDE, it is also applicable to other tools as is apparanet from teh comments. (BTW I am not allowed to edit this answer directly, perhaps the author can add it?)

避免代码中出现NullPointerException问题的另一种方法是使用@Nullable和@NotNull注释。以下答案提供了有关这方面的更多信息。虽然这个答案是关于IntelliJ IDE的,但它也适用于其他工具,如评论中所示。(顺便说一句,我不能直接编辑这个答案,也许作者可以添加它?)

I understood everything you wrote there, but only because I've been coding for a while and know what a 'pointer' and a 'reference' are (and what null is, for that matter). When I try to dive right into explanations like that, my students look at me crosseyed, because there's not enough background.

我理解您在那里写的所有内容,但这仅仅是因为我已经编写了一段时间的代码,并且知道什么是“指针”和“引用”(就这一点而言,什么是NULL)。当我试图一头扎进这样的解释中时,我的学生们对我怒目而视,因为没有足够的背景资料。

A more common way to get a NullPointerException in practice would be forgetting to explicitly initialize a member variable to something other than null before using it, like this. With local variables, the compiler would catch this error, but in this case it doesn't. Maybe that would make a useful addition to your answer?

实际上,获取NullPointerException的一种更常见的方法是忘记在使用成员变量之前将其显式初始化为非空的值,如下所示。使用局部变量,编译器可以捕捉到这个错误,但在本例中却没有。也许这会对您的答案有所帮助?

@EJP I think your points are valid, so I've updated the answer to be clearer and to avoid saying 'points to null' where it did.

@EJP我认为你的观点是正确的,所以我更新了答案,以使答案更清晰,并避免在答案正确的地方说‘Points to Null’。

@StevePowell I indicated a long time ago that I didn't want my answer to change. Please respect the intent of the original author.

@史蒂文·鲍威尔我很久以前就表示,我不希望我的答案改变。请尊重原作者的意图。

Sorry, I was "improving the answer" as requested in the top of this stackoverflow item (This question's answers are a collaborative effort: if you see something that can be improved, just edit the answer to improve it!) I disagree that your version is better, IMO @EJB has valid points; but you are quite welcome to keep your answer intact, confusing though it is.

对不起,我只是按照这个堆栈溢出项目顶部的要求“改进答案”(此问题的答案是协作完成的:如果您看到可以改进的地方,只需编辑答案以改进它!)我不同意您的版本更好,IMO@ejb有正确的观点;但非常欢迎您完整地保留您的答案,尽管它令人困惑。

@RuchirBaronia A debugger allows you to step through a program line by line to see which methods are called and how variables are changed. IDEs should have some tools to do this. See vogella.com/tutorials/EclipseDebugging/article.html for example.

@RuchirBaronia调试器允许您逐行调试程序,以查看调用了哪些方法以及变量是如何更改的。IDE应该有一些工具来实现这一点。例如,请参见vogella.com/tutorials/EclipseDebugging/article.html。

@RuchirBaronia You set breakpoints on the methods around any NullPointerExceptions as seen in the stacktrace, and check the values of variables against what you expect them to be. If you know a variable is null when it shouldn't be, then you can set breakpoints around any code that changes the value. There are also conditional breakpoints you can use which will tell you when a value changes.

@RuchirBaronia您可以在堆栈跟踪中看到的任何NullPointerExceptions周围的方法上设置断点,并根据您期望的值检查变量的值。如果您知道某个变量是空的,而它不应该是空的,那么可以在任何更改该值的代码周围设置断点。您还可以使用条件断点,这些断点将在值发生更改时告知您。

i suggest also static analysis tools, like FINDBUGS en.m.wikipedia.org/wiki/FindBugs

我还建议使用静态分析工具,如FINDBUGS en.m.wikipedia.org/wiki/FindBugs

If we give System.out.println(a.length()); // NullPointerException will be thrown, to skip this we can handle with try catch block. thank you

如果我们给出System.out.println(a.long());//将抛出NullPointerException,要跳过这一点,我们可以使用try Catch块来处理。谢谢

Keep it simple, I like this answer, add this if you consider correct - Access to uninitialized attribute of an object

保持简单,我喜欢这个答案,如果你认为正确的话,加上这个-访问对象的未初始化属性

@Emiliano - simply accessing an initialized attribute does not cause an NPE. It is what you >>do<< with the uninitialized attribute value that causes the NPE.

@Emily iano-简单地访问已初始化的属性不会导致NPE。是您>>对未初始化的属性值所做的操作<<导致了NPE。

If you want more cases: 1) using a null as the target of a synchronized block, 2) using a null as the target of a switch, and unboxing null.

如果您想要更多的情况:1)使用空值作为同步块的目标,2)使用空值作为开关的目标,以及取消装箱空值。

"A NULL pointer is one that points to nowhere" I disagree. Null pointers don't point to nowhere, they point to null values.

我不同意“空指针无处可指”的说法。空指针不会指向任何地方,它们指向空值。

In j2ee projects,Nullpointer exception is very common.Some cases reference variables got null values.So You should check the variable initialization properly.And during conditional statement you should always check that flag or reference contains null or not like:- if(flag!=0) { ur code that uses flag }

在J2EE项目中,空指针异常是非常常见的。有些引用变量的值为空值。所以你应该正确检查变量的初始化。在条件语句中,你应该总是检查标志或引用是否包含空或不像:-if(标志!=0){ur代码使用标志}

It is worth mentioning that some IDEs (e.g. Eclipse) offer automatic nullity analisys based on customizable annotations (e.g. @Nullable as listed above) and warn about potential errors. It is also possible to infer and generate such annotations (e.g. IntelliJ can do that) based on existing code structure.

值得一提的是,一些IDE(例如,Eclipse)提供了基于可定制注释(例如,上面列出的@Nullable)的自动无效性分析,并警告潜在的错误。还可以基于现有代码结构推断和生成此类注释(例如,IntelliJ可以这样做)。

First thing should do is before using a nullable object, you should check whether is it null, using if (obj==null).If it is null then you should write code to handle that also.

在使用可为空的对象之前,首先应该使用if(obj==NULL)检查它是否为空。如果它为空,那么你也应该编写代码来处理它。

IMO, it is preferable to avoid returning null objects in methods when possible and use annotation when null input parameters are not allowed in order to, by contract, reduce the amount of ´if (obj==null)´ in the code and improve the code readability.

如果可能,最好避免在方法中返回空对象,并在不允许使用空输入参数时使用注释,以便根据合同减少代码中的“if(obj==空)”的数量并提高代码的可读性。

Read this ... before you accept these "best practices" as truth: satisfice.com/blog/archives/27

读读这个..。在你接受这些“最佳实践”作为真理之前,请登录:Squirefie.com/博客/存档/27

While this is a nice example, may I ask what it adds to the question that isn't already covered by all the other answers?

虽然这是一个很好的例子,但我可以问一下,它对所有其他答案都没有涵盖的问题增加了什么?

It is simply inappropriate to use the word "uninitialized" here. The example you shown is in fact "initialized", and it is initialized with null. For uninitialized variables, compiler will complain to you.

在这里使用“未初始化”一词是完全不合适的。您显示的示例实际上是“初始化的”,并且它是用NULL初始化的。对于未初始化的变量,编译器会向您投诉。

A NullPointerException often occurs when calling method of an instance.For example, if you declare a reference but does not make it point to any instance, NullPointerException will happen when you call its method. such as: YourClass ref = null; // or ref = anotherRef; // but anotherRef has not pointed any instance ref.someMethod(); // it will throw NullPointerException. Generally fix it in this way: Before the method is called, determine whether the reference is null. such as: if (yourRef != null) { yourRef.someMethod(); }

在调用实例的方法时,经常会出现NullPointerException异常。例如,如果声明了一个引用,但没有使其指向任何实例,则在调用其方法时会发生NullPointerException。例如:YourClass ref=NULL;//或ref=antherRef;//但antherRef尚未指向任何实例ref.ome Method();//它将引发NullPointerException。通常这样修复:在调用方法之前,确定引用是否为空。如:if(YourRef!=NULL){YourRef.ome方法();}

Or use exception capture: such as: try { yourRef.someMethod(); } catch (NullPointerException e) { // TODO }

或者使用异常捕获:例如:try{YourRef.ome Method();}Catch(NullPointerException E){//TODO}

operation on uninitialized object at instance level(not the class level) will lead to NullPointerException. operation need to be instance specific. if operation is at class level, saying calling a static method on uninitialized object then it will not throw NullPointerException exception. Even primitive wrapper class objects throws NullPointerException.

在实例级(非类级)对未初始化的对象进行操作会导致NullPointerException异常。操作需要特定于实例。如果操作是在类级别进行的,即对未初始化的对象调用静态方法,则不会引发NullPointerException异常。即使是原始包装类对象也会抛出NullPointerException。

1. NullPointerException is a RuntimeException, that means will appear when your program is running, you will not at compilation time.! :(, but most of the IDE help you to discover this. 2. Minimize the use of the keyword 'null' in assignment statements. :) Reference url:

1.NullPointerException是一个RUNTIME异常,这意味着你的程序在运行时会出现,而不会在编译时出现。!:(,但大多数IDE都会帮助你发现这一点。2.尽量减少在赋值语句中使用关键字‘NULL’。:)引用URL:

@tomj0101 I'm thoroughly unclear as to why you made that comment... But to your second point, a pattern before Optional was to return null. The keyword is fine. Knowing how to guard against it is critical. This offers one common occurrence of it and ways to mitigate it.

@tomj0101我完全不清楚你为什么会做出这样的评论...但对于您的第二点,Optional之前的模式是返回NULL。关键字没问题。知道如何防范它是至关重要的。这提供了它的一种常见情况以及缓解它的方法。

@Shomu: At what point do I even suggest that it should be caught?

@Shomu:在什么情况下,我甚至应该建议应该抓住它?

35 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com