Static Fields on a Null Reference in Java

Static fields on a null reference in Java

That behaviour is specified in the Java Language Specification:

a null reference may be used to access a class (static) variable without causing an exception.

In more details, a static field evaluation, such as Primary.staticField works as follows (emphasis mine) - in your case, Primary = main.getNull():

  • The Primary expression is evaluated, and the result is discarded. [...]
  • If the field is a non-blank final field, then the result is the value of the specified class variable in the class or interface that is the type of the Primary expression. [...]

Accessing a static field with a NULL object in Java

As opposed to regular member variables, static variables belong to the class and not to the instances of the class. The reason it works is thus simply because you don't need an instance in order to access a static field.

In fact I'd say it would me more surprising if accessing a static field could ever throw a NullPointerException.

If you're curious, here's the bytecode looks for your program:

// Create TestNull object
3: new #3; //class TestNull
6: dup
7: invokespecial #4; //Method TestNull."<init>":()V

// Invoke the temp method
10: invokevirtual #5; //Method TestNull.temp:()LTestNull;

// Discard the result of the call to temp.
13: pop

// Load the content of the static field.
14: getstatic #6; //Field TestNull.field:I

This is described in the Java Language Specification, Section 15.11.1: Field Access Using a Primary. They even provide an example:

The following example demonstrates that a null reference may be used to access a class (static) variable without causing an exception:

class Test {
static String mountain = "Chocorua";
static Test 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

Why does Java compiler allow static variable access through null object?

To add some additional info to the current answers, if you disassemble your class file using:

javap -c TestClass1

You'll get:

Compiled from "TestClass1.java"
public class TestClass1 extends java.lang.Object{
static int a;

public TestClass1();
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: return

public static void main(java.lang.String[]);
Code:
0: aconst_null
1: astore_1
2: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
5: aload_1
6: pop
7: getstatic #3; //Field a:I
10: invokevirtual #4; //Method java/io/PrintStream.println:(I)V
13: return

static {};
Code:
0: bipush 10
2: putstatic #3; //Field a:I
5: return
}

Here you can see that the access to the static field is done in line 7 by the getstatc instruction. Whenever a static field is accessed through code, a corresponding getstatic instruction will be generated in the .class program file.

*static instructions have the particularity that they don't requiere a reference to the object instance to be in the stack prior to calling them (like, for example invokevirtual which does require an object ref in the stack), they resolve the field/method using just an index to the run time constant pool that will be later used to solve the field reference location.

That's a technical reason for the warning "The static field should be accessed in a static way" that some IDEs will throw at you when you write t1.a, because the object instance is unnecessary to resolve the static field.

Call static method on null object

Accessing a static method or variable can be done via a null reference for the class that contains that static method/variable.

Since name is static, getFoo().name has the same result as Foo.name or just name, regardless of whether or not getFoo() returns null.

However, it is always better to use the class name when accessing a static method/variable, since it makes it clear that you intended to access a static member.

How static fields are referenced through objects?

The instance is in fact not used. Java uses the type of the variable, and then reads the static (class) field.

That's why even a null with the correct type won't raise a null pointer exception.

Try this:

Foo foo1 = null;
int valFromObject = foo1.statValue; //will work

Or this:

int valFromNull = ((Foo)null).statValue; //same thing

Accessing static class members through instances is discouraged for obvious reasons (the most important being the illusion that an instance member is being referenced, in my opinion). Java lets use foo1.statValue, with a warning ("The static field Foo.statValue should be accessed in a static way" as reported by my IDE).

Why not a NullPointerException while accessing static with null reference?

From Java Language Specifications

Receiver Variable Is Irrelevant For static Field Access

The following program demonstrates that a null reference may be used to access a class (static) variable without causing 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 though the result of favorite() is null, a NullPointerException is not thrown. That "Mount " is printed demonstrates that the Primary expression is indeed fully evaluated at run time, despite the fact that only its type, not its value, is used to determine which field to access (because the field mountain is static).

Implies even though primary expression (Here is instance) is evaluated at run time, but its value is discarded and only its type is considered.



Related Topics



Leave a reply



Submit