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.