在Java中使用NULL对象访问静态字段

以下简单的代码片段工作正常,并使用null对象访问静态字段。

final class TestNull { public static int field=100; public TestNull temp() { return(null); } } public class Main { public static void main(String[] args) { System.out.println(new TestNull().temp().field); } } 

在上面的代码中,声明System.out.println(new TestNull().temp().field); 其中静态字段字段与NULL对象new TestNull().temp() ,仍然返回它的正确值,它是100而不是在Java中抛出空指针exception! 为什么?

与常规成员变量相反,静态变量属于类 ,而不属于类的实例。 它工作的原因仅仅是因为您不需要实例来访问静态字段。

事实上,如果访问静态字段可能会抛出NullPointerException我会说更令我惊讶

如果你很好奇,这里是字节码查找你的程序:

 // Create TestNull object 3: new #3; //class TestNull 6: dup 7: invokespecial #4; //Method TestNull."":()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 

这在Java语言规范的第15.11.1节:使用主节点的字段访问中进行了描述 。 他们甚至提供了一个例子:

以下示例演示了可以使用null引用来访问类(静态)变量而不会导致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); } } 

它编译,执行和打印:

Chocorua山

静态变量在类的每个对象之间共享。 因此,当您返回的实际对象引用为null时(在C ++中:TestNull * temp = null;),您有一个TestNull类型的对象,Java可以使用它来查找该类的静态值。

请记住,Java对象确实是指针。 指针有一种类型。 从那种类型,Java可以识别某些信息,即使它指向null。

静态字段与类关联,而不是该类的实例。 因此,您不需要对象的实例来访问静态字段。

您也可以通过调用TestNull.field来访问该字段