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

Bha*_*esh 10 java

以下简单的代码片段工作正常,并使用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);
    }
}
Run Code Online (Sandbox Code Playgroud)

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

aio*_*obe 12

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

事实上,如果访问一个静态字段可能会抛出一个,我会更加惊讶NullPointerException.

如果你很好奇,这里的字节码代表你的程序:

// 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
Run Code Online (Sandbox Code Playgroud)

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

以下示例演示了可以使用null引用来访问类(静态)变量而不会导致异常:

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);
        }
}
Run Code Online (Sandbox Code Playgroud)

它编译,执行和打印:

Chocorua山


oni*_*nit 5

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

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