问:定义一个赋值为 null 的类类型变量名 a,能否通过 a 不进行实例化而直接访问其 static 属性或者方法?
答:答案是肯定的,能。譬如如下例子:
public class Test {
public static int NUM = 100;
public static void funcDo() {
System.out.println("Num = "+ NUM);
}
public static void main(String[] args) {
Test test = null;
System.out.println(test.NUM);
test.funcDo();
}
}
上面代码的运行结果可以输出 100 和 Num = 100。不过不建议这么写代码。至于为什么其实很简单,直接看上面代码段的字节码,如下:
$ javap -v Test.class
......
//编译后常量池已经替换成了与 null 无关而与类相关的 static 成员,#7 与 #12。
Constant pool:
......
//重点!!!
#7 = Fieldref #13.#39 // Test.NUM:I
......
//重点!!!
#12 = Methodref #13.#45 // Test.funcDo:()V
#13 = Class #46 // Test
......
{
......
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=2, locals=2, args_size=1
//把null入栈
0: aconst_null
1: astore_1
2: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
5: aload_1
6: pop
//重点!使用了常量池的#7
7: getstatic #7 // Field NUM:I
10: invokevirtual #11 // Method java/io/PrintStream.println:(I)V
13: aload_1
14: pop
//重点!使用了常量池的#12
15: invokestatic #12 // Method funcDo:()V
18: return
......
}
SourceFile: "Test.java"
很明显可以看出,当我们通过一个对象的引用访问静态成员属性或者方法时,访问操作只与所声明的引用类型相关;与引用对象是否为 null 无关,因为访问静态成员不需要实例化对象;即便引用不为 null,也与运行时多态无关,因为静态成员是类相关的。