Why is there a NullPointerException when accessing static with a null reference?

Here in the following code we get the value i in the null reference, although NPE does not exist.

 public class Test { static int i = 10; Test getTest() { return null; } public static void main(String args[]) { Test t = new Test(); System.out.println(t.getTest()); System.out.println(t.getTest().i); } } 

Output

 null 10 
+6
source share
8 answers

From the Java Language Specification

Receiver Variable Is Irrelevant For static Field Access

The following program demonstrates that a null reference can be used to access a class variable (static) without throwing an exception:

 class Test3 { static String mountain = "Chocorua"; static Test3 favorite(){ System.out.print("Mount "); return null; } public static void main(String[] args) { System.out.println(favorite().mountain); } } 

It compiles, executes, and prints:

 Mount Chocorua 

Even if the result of the favorite () function is null, a NullPointerException is not thrown. What Mount prints shows that the Primary expression is indeed fully evaluated at runtime, even though its type is used to determine which field needs access, not its value (since the field is static )

It is ignored, although the primary expression (Here is instance) is evaluated at run time, but its value is discarded and only its type is considered.

+2
source

Speaking informally, you can think about it

 System.out.println(t.getTest().i); 

as equivalent

 System.out.println(Test.i); 

because i is static.

Perhaps this is the easiest answer.

Strictly speaking, they are not equivalent. Actually
getTest() is called, but its return value is not used
to access field i , as shown later in this test.
 public class Test { static int i = 10; Test getTest() { System.out.println("Method getTest() called!"); return null; } public static void main(String args[]) { Test t = new Test(); System.out.println(t.getTest()); System.out.println(t.getTest().i); } } 
+7
source

i is a static variable; an instance is not required to get its value.

+4
source

The generated bytecode is as follows:

 18 getstatic java.lang.System.out : java.io.PrintStream [24] 21 aload_1 [t] 22 invokevirtual experiments.Experiments.getTest() : experiments.Experiments [30] 25 pop 26 getstatic experiments.Experiments.i : int [10] 29 invokevirtual java.io.PrintStream.println(int) : void [38] 

As you can see, t.getTest() indeed called (21,22), but its result is not used (25). Access to field i carried out in a static way (26). Java Bytecode does not have access to static members through an instance. Note that this means t.getTest().i and Test.i are not equivalent expressions! In a hypothetical syntax, an equivalent might look like this (using semantics that I would find intuitive for this syntax:

 System.out.println( {t.getTest(); return Test.i;} ); 

Note that the same is true for the test field: t.test.i is different from Test.i Although getting a field cannot have any side effects and is not a valid expression in itself, access to the fields can still be recommended by AspectJ or something similar.

+4
source
  Test t = new Test(); // initialize t 

Here t not null since it was initialized. This way you are not getting a NullPointerException .

In the following case, when you expected a NullPointerException , since t.getTest() returned null ,

 t.getTest().i; 

i is a static variable and you don't need an instance to access static variables, you can just access them directly. That way you are not getting a NullPointerException either.

Besides,

 System.out.println(i); // is an another way to access static i 
+2
source

Static methods or variables do not need an object reference. You can call it, even an object reference is null.

+1
source

To be more specific,

When accessing the Static variable, the compiler will generate the getStatic command corresponding to this Static , and it will be used to access this Static . thus, static instances are instance independent, they are resolved using the field / method, using only the index into the run-time constant pool , which will later be used to decide the location of the field reference.

See this SO answer for more details: fooobar.com/questions/51284 / ...

+1
source

Simply put, the compiler takes statics from the def class, and not from the object. That is why you can replace t.getTest().i with Test.i and it will be the same.

0
source

All Articles