Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java static field from null [duplicate]

I found this code on the Internet, and would love for someone to explain it to me...

public class Foo {
    static int fubar = 42;

    public static void main(String[] args) {
        System.out.println(((Foo) null).fubar);
    }
}

This code compiles and works correctly, outputting the result 42.

How is it possible that the variable fubar is accessed from a null without throwing a NullPointerException?

like image 917
user710818 Avatar asked Jul 21 '11 20:07

user710818


2 Answers

It's not actually looking for the field on null, because static methods and fields don't require an instance. The cast makes the type of the expression Foo, and fubar is a known static field on Foo, so the compiler and JVM have no issue.

Normally, you'd access the field by saying Foo.fubar. However, Java is nice enough to provide a shortcut: if you try to access a static field or method on an instance expression of a given type, it will treat it as if you had said [SomeType].theField. That's what's occurring here.

like image 82
dlev Avatar answered Sep 25 '22 15:09

dlev


Because the field fubar is declared static, there is only one field anywhere actually named Foo.fubar. Each instance of Foo shares this one copy. When you access this field out of a Foo object, Java doesn't try following the object reference to find it. Instead, it looks up the object in a specially-defined location that can be accessed independently of any reference. Consequently, if you try looking up this field of the null object, you can do so without causing any sort of NullPointerException, since the object is never referenced.

EDIT: Bytecode is definitely in order! Given this source file:

public class Foo {
    static int fubar;
    public Foo() {
        ((Foo)null).fubar = 137;
    }
}

Here's the generated bytecode:

0:  aload_0
1:  invokespecial   #1; //Method Object."<init>":()V
4:  aconst_null
5:  checkcast   #2; //class Foo
8:  pop
9:  sipush  137
12: putstatic   #3; //Field fubar:I
15: return

Notice that line 12 uses the putstatic opcode, which stores a value into a static field. It doesn't reference a receiver object of any sort. In fact, if you'll notice, the generated bytecode (lines 4-8) does a cast of null to Foo, but then immediately issues a pop opcode to pop it off the stack. It's never referenced anywhere else in the bytecode.

like image 31
templatetypedef Avatar answered Sep 25 '22 15:09

templatetypedef