119

staticJava 中的成员(static字段或static方法)与其各自的类相关联,而不是与此类的对象相关联。以下代码尝试访问null引用上的静态字段。

public class Main
{
    private static final int value = 10;

    public Main getNull()
    {
        return null;
    }

    public static void main(String[] args)
    {
        Main main=new Main();
        System.out.println("value = "+main.getNull().value);
    }
}

虽然main.getNull()返回null,但它可以工作并显示value = 10。这段代码是如何工作的?

4

5 回答 5

93

Java 语言规范中指定了该行为:

空引用可用于访问类(静态)变量而不会导致异常。

更详细地说,静态字段评估,例如Primary.staticField如下工作(强调我的) - 在你的情况下,Primary = main.getNull()

  • 对 Primary 表达式求值,并丢弃结果。[...]
  • 如果该字段是非空白最终字段,则结果是作为主表达式类型的类或接口中指定类变量的值。[...]
于 2012-07-20T13:06:18.130 回答
19

因为,正如您所说,静态字段与实例无关。

从实例引用访问静态字段的能力(正如您所做的那样)只是一种语法糖,没有其他含义。
您的代码编译为

main.getNull(); 
Main.value
于 2012-07-20T13:05:32.263 回答
3
  1. 使用类名访问static成员是合法的,但没有写到不能static使用对象引用变量访问成员。所以它在这里工作。

  2. null允许对象引用变量访问类static变量,而不会在编译或运行时引发异常。

于 2012-07-20T13:10:14.480 回答
3

当您在编译时访问带有对象的静态变量或方法时,它会转换为类名。例如:

Main main = null;
System.out.println(main.value);

它将打印静态变量值的值,因为在编译时它将被转换为

System.out.println(Main.value);

证明:

下载反编译器并将您的 .class 文件反编译为 .java 文件,您可以看到所有静态方法或变量引用的对象名称自动替换为类名称。

于 2012-12-20T09:52:52.010 回答
2

静态变量和方法总是属于类。因此,当我们创建任何对象时,只有非静态变量和方法与对象一起进入堆,但静态驻留在类的方法区域中。这就是为什么当我们尝试访问静态变量或方法时,它会转换为类名点变量或方法名。

请参阅以下链接以获取更多详细信息。

http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html

于 2012-12-26T14:39:48.680 回答