问题:什么是NullPointerException,我该如何解决?

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

可以使用哪些方法/工具确定原因,以阻止异常导致程序过早终止?

标签:java,nullpointerexception

Q: What is a NullPointerException, and how do I fix it?

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

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

回答1:

当您声明引用变量(即对象)时,您实际上是在创建指向对象的指针。考虑以下代码,在其中声明基本类型int的变量:

int x;
x = 10;

在此示例中,变量xint,Java会为您将其初始化为0。当您在第二行为其分配10的值时,您的10的值将被写入x所引用的存储位置。 / p>

但是,当您尝试声明引用 type 时,会发生一些不同的事情。输入以下代码:

Integer num;
num = new Integer(10);

第一行声明了一个名为num的变量,但实际上它尚未包含原始值。相反,它包含一个指针(因为类型是Integer,它是引用类型)。既然您尚未指出要指向的内容,Java会将其设置为null,这表示" 我指向的是什么都没有 "。

在第二行中,使用new关键字实例化(或创建)Integer类型的对象和指针变量num被分配给该Integer对象。

NullPointerException在您声明变量但未创建对象并在尝试使用变量的内容之前将其分配给变量(称为 dereferencing )时发生。因此,您指向的是实际上不存在的东西。

当使用.访问方法或字段,或使用[为数组建立索引时,通常会取消引用。

如果在创建对象之前尝试取消引用num,则会得到NullPointerException。在大多数情况下,编译器会发现问题,并告诉您" num可能尚未初始化",但是有时您可能会编写不直接创建对象的代码。

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

public void doSomething(SomeObject obj) {
   //do something to obj
}

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

doSomething(null);

在这种情况下,objnull。如果该方法旨在对传入的对象做某事,则抛出NullPointerException是适当的,因为它是程序员的错误,程序员将需要该信息来进行调试。请在异常消息中包含对象变量的名称,例如

Objects.requireNonNull(a, "a");

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

最后,如何使用堆栈跟踪来查明异常和原因

可以使用哪些方法/工具确定原因,以阻止异常导致程序过早终止?

带有findbug的声纳可以检测NPE。 声纳能否动态捕获由JVM引起的空指针异常

A1:

When you declare a reference variable (i.e. an object) you are really creating a pointer to an object. Consider the following code where you declare a variable of primitive type int:

int x;
x = 10;

In this example, the variable x is an int and Java will initialize it to 0 for you. When you assign it the value of 10 on the second line, your value of 10 is written into the memory location referred to by x.

But, when you try to declare a reference type, something different happens. 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 primitive value yet. Instead, it contains a pointer (because the type is Integer which is a reference type). Since you have not yet said what to point to, Java sets it to null, which means "I am pointing to nothing".

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

The NullPointerException occurs when you declare a variable but did not create an object and assign to the variable before trying to use the contents of the variable (called dereferencing). So you are pointing to something that does not actually exist.

Dereferencing usually happens when using . to access a method or field, or using [ to index an array.

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.

For instance, you may have a method as follows:

public void doSomething(SomeObject obj) {
   //do something to obj
}

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:

doSomething(null);

In which case, obj is null. If the method is intended to do something to the passed-in object, it is appropriate to throw the NullPointerException because it's a programmer error and the programmer will need that information for debugging purposes. Please include the name of the object variable in the exception message, like

Objects.requireNonNull(a, "a");

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:

/**
  * @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 findbugs can detect NPE. Can sonar catch null pointer exceptions caused by JVM Dynamically

回答2:

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

我想出的最快的示例代码来说明NullPointerException是:

public class Example {

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

}

main内部的第一行,我将Object引用obj显式设置为等于null 。这意味着我有一个引用,但它没有指向任何对象。之后,我尝试通过在其上调用方法来将引用当作指向对象的方式来对待。这会导致NullPointerException,因为在引用指向的位置没有任何代码可执行。

(这是一种技术,但是我认为值得一提:指向null的引用与指向无效内存位置的C指针不同。null指针从字面上不指向任何地方的 ,这与指向碰巧是无效的位置有细微差别。)

A2:

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.

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

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.

(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.)

回答3:

什么是NullPointerException?

JavaDocs 。他们有以下内容:

在需要对象的情况下应用程序尝试使用null时抛出。其中包括:

  • 调用空对象的实例方法。
  • 访问或修改空对象的字段。
  • 以null的长度作为数组。
  • 访问或修改null插槽,就好像它是一个数组一样。
  • 将null视为Throwable值。

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

在这种情况下,如果您尝试对synchronized使用空引用,也会引发此异常,根据JLS

SynchronizedStatement:
    synchronized ( Expression ) Block
  • 否则,如果Expression的值为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方法中)引发了异常。查看该行,并通过添加 logging语句或使用 debugger 来检查哪些值为空。我们发现s为null,并在其上调用length方法将引发异常。我们可以看到,从方法中删除s.length()时,程序停止引发异常。

这些值的来源

下一步检查此值的来源。通过跟踪该方法的调用者,我们看到sprint()方法中的printString(name)一起传入,而< code> this.name 为空。

应在何处设置这些值

在哪里设置this.name?在setName(String)方法中。通过更多的调试,我们可以看到根本没有调用此方法。如果调用了该方法,请确保检查调用这些方法的 order ,并且在print方法之后不调用 set方法。

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

其他修复程序

变量可以具有默认值(并且setName可以防止将其设置为null):

private String name = "";

printprintString方法都可以检查是否为空,例如:

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

或者您可以设计类,以便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();
    }
}

另请参见:

我仍然找不到问题

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

A3:

What is a NullPointerException?

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

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:

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:

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.

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.

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.

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

Other fixes

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

private String name = "";

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

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).

回答4:

问题:什么原因导致NullPointerException(NPE)?

您应该知道,Java类型分为原始类型(booleanint等)和引用类型。 Java中的引用类型使您可以使用特殊值null,这是Java表示"无对象"的方式。

每当您的程序尝试使用null时,就会在运行时抛出NullPointerException,就好像它是真实的引用一样。例如,如果您编写此代码:

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

标记为" HERE"的语句将尝试在null引用上运行length()方法,这将引发NullPointerException。

有很多方法可以使用null值,该值将导致NullPointerException。实际上, 可以使用null进行而不会引起NPE的唯一事情是:

  • 将其分配给参考变量或从参考变量中读取
  • 将其分配给数组元素或从数组元素中读取(前提是数组引用本身不为null!)
  • 将其作为参数传递或作为结果返回,或者
  • 使用==!=运算符或instanceof进行测试。

问题:如何读取NPE堆栈跟踪记录?

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

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

第一个观察:编译成功!程序中的问题不是编译错误。这是运行时错误。 (某些IDE可能会警告您的程序将始终引发异常……但是标准的javac编译器不会引发异常。)

第二个观察:当我运行程序时,它输出两行" gobbledy-gook"。 错误!这不是傻瓜。这是一个堆栈跟踪...,它提供了重要信息,如果您花时间仔细阅读它,它将帮助您查找代码中的错误。

所以让我们看一下它的意思:

Exception in thread "main" java.lang.NullPointerException

堆栈跟踪的第一行告诉您许多信息:

  • 它告诉您抛出异常的Java线程的名称。对于一个只有一个线程(像这样的线程)的简单程序,它将是" main"。让我们继续...
  • 它告诉您引发的异常的全名;即java.lang.NullPointerException
  • 如果异常具有关联的错误消息,则将在异常名称之后输出。 NullPointerException在这方面很不寻常,因为它很少有错误消息。

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

at Test.main(Test.java:4)

这告诉我们很多事情:

  • "在Test.main上"表示我们在Test类的main方法中。
  • " Test.java:4"给出了该类的源文件名,并且它告诉我们发生此情况的语句在文件的第4行中。

如果您计算上面文件中的行,则第4行是我用" HERE"注释标记的行。

请注意,在一个更复杂的示例中,NPE堆栈跟踪中将有很多行。但是您可以确定第二行(第一行" at"行)将告诉您NPE的抛出位置 1

简而言之,堆栈跟踪将明确告诉我们该程序的哪个语句引发了NPE。

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

问题:如何在我的代码中查找NPE异常的原因?

这是困难的部分。简短的答案是对堆栈跟踪,源代码和相关API文档提供的证据进行逻辑推断。

让我们首先用一个简单的例子(上面)进行说明。我们首先查看堆栈跟踪告诉我们的那行是NPE发生的地方:

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

那怎么扔NPE?

实际上只有一种方法:只有当foo的值为null时,它才会发生。然后,我们尝试在null和.... Bang!

上运行length()方法。

但是(我听到你说)如果NPE被抛出在length()方法调用内怎么办?

好吧,如果发生这种情况,堆栈跟踪看起来会有所不同。第一行" at"表示该异常是在java.lang.String类的某行中引发的,而Test.java的第四行将是第二行"在"行。

那么null是哪里来的呢?在这种情况下,很明显,很明显,我们需要进行修复。 (将非空值分配给foo。)

好的,让我们尝试一个更棘手的示例。这将需要一些逻辑推论

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)
$ 

因此,现在我们有两个" at"行。第一个用于此行:

return args[pos].length();

第二个用于此行:

int length = test(foo, 1);

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

  • 如果bar的值为null,则bar[pos]将抛出NPE。
  • 如果bar[pos]的值为null,则在其上调用length()会抛出NPE。

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

bar来自哪里?它是test方法调用的参数,如果我们看一下test的调用方式,我们可以看到它来自foo静态变量。另外,我们可以清楚地看到我们将foo初始化为一个非null值。这足以暂时驳斥该解释。 (从理论上讲,可以将 foo更改为null ...,但这在这里没有发生。)

那我们的第二种情况呢?好吧,我们可以看到pos1,这意味着foo[1]必须为null。有可能吗?

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

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

我们为String[]分配了两个元素,它们被初始化为null 。之后,我们没有更改foo的内容...因此foo[1]仍为null

A4:

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".

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:

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

the statement labelled "HERE" is going to attempt to run the length() method on a null reference, and this will throw a 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:

  • 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.)

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.

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.

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.

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.

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

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

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.

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:

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

How can that throw an 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!

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

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.

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.)

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:

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:

  • 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.)

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

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.

回答5:

就像您正在尝试访问null的对象一样。考虑以下示例:

TypeA objA;

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

也请参见以下示例:

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

A5:

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.

See this below example as well:

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

回答6:

在需要对象的情况下,应用程序尝试使用null时,将引发null指针异常。其中包括:

  1. 调用null对象的实例方法。
  2. 访问或修改null对象的字段。
  3. null的长度作为数组。
  4. 访问或修改null的插槽,就好像它是一个数组一样。
  5. 抛出null就像它是一个Throwable值一样。

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

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

A6:

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

  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

回答7:

null指针是指向无处的指针。当取消引用指针p时,您说"给我存储在" p"中的位置的数据。当pnull指针时,存储在p中的位置是nowhere,您说的是"在位置'nowhere'处给我数据"。显然,它无法执行此操作,因此它会引发null指针异常

通常,这是因为某些内容未正确初始化。

A7:

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.

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

回答8:

已经有很多解释来解释它是如何发生的以及如何解决它,但是您还应该遵循最佳实践,以避免 NullPointerException 完全。< / p>

另请参见:最佳做法的好清单

非常重要的是,我会很好地利用final修饰符。 只要适用于Java,就使用"最终"修饰符

摘要:

  1. 使用final修饰符强制执行良好的初始化。
  2. 避免在方法中返回null,例如在适用时返回空集合。
  3. 使用注释 @NotNull @Nullable
  4. 快速失败,并使用断言避免空对象在不应该为空的情况下在整个应用程序中传播。
  5. 首先对已知对象使用等于:if("knownObject".equals(unknownObject)
  6. 相对于toString(),更喜欢valueOf()
  7. 使用null安全 <代码> StringUtils 方法StringUtils.isEmpty(null)

A8:

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.

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

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).

回答9:

空指针异常表示您正在使用对象而未对其进行初始化。

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

public class Student {

    private int id;

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

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

以下代码为您提供了空指针异常。

public class School {

    Student student;

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

因为您使用的是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");
        }
    }
}

A9:

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:

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

回答10:

在Java中,所有内容(不包括原始类型)都以类的形式出现。

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

  1. 声明
  2. 初始化

示例:

  • 声明:Objectobject;
  • 初始化:object=newObject();

与数组概念相同:

  • 声明:Itemitem[]=newItem[5];
  • 初始化:item[0]=newItem();

如果不提供初始化部分,则会出现NullPointerException

A10:

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

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.

回答11:

Java 中,您声明的所有变量实际上都是对"对象(或图元),而不是对象本身。

当您尝试执行一个对象方法时,引用会要求活动对象执行该方法。但是,如果引用引用的是NULL(无,零,无效,nada),则该方法将无法执行。然后,运行时将引发NullPointerException,让您知道这一点。

您的引用"指向"为null,因此为" Null->指针"。

对象位于VM内存空间中,唯一的访问方法是使用this引用。举个例子:

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

在代码的另一个位置:

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...

这是一个重要的知识-当不再有对对象的引用时(在上面的示例中,当referenceotherReference都指向null时),则该对象是"无法到达的"。我们无法使用它,因此已准备好对该对象进行垃圾回收,并且在某些时候,VM将释放该对象使用的内存并分配另一个。

A11:

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

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.

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:

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.

回答12:

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

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

如果比较顺序相反,则可以避免使用此特定的NPE。也就是说,在保证的非null对象上使用.equals

数组内的所有元素初始化为它们的共同初始值;对于任何类型的对象数组,这意味着所有元素均为null

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

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

A12:

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

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.

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));
}
回到顶部