java 静态初始化与继承

public class Main {

    public static void main(String[] args) {
        System.out.println(B.x);
    }

}
class A {
    public static String x = "x";
}
class B extends A {
    static {
        System.out.print("Inside B.");
    }
}

问:为什么输出将是:.但不是:xInside B.x


答案 1

对 发出以下字节码的引用:B.x

getstatic       #3   <Field int B.x>

根据 Java 虚拟机规范

Java 虚拟机指令 anewarray、checkcast、getfield、getstatic、instanceof、invokedynamic、invokeinterface、invokespecial、invokestatic、invokevirtual、ldc、ldc_w、multianewarray、new、putfield 和 putstatic 对运行时常量池进行符号引用。执行任何这些指令都需要解析其符号引用

因此,JVM 应该解析B.x 的符号引用。字段分辨率指定如下:

要将未解析的符号引用从 D 解析为类或接口 C 中的字段,必须首先解析字段引用对 C 的符号引用 (§5.4.3.1)。

...

解析字段引用时,字段解析首先尝试在 C 及其超类中查找引用的字段:

如果 C 声明的字段具有字段引用指定的名称和描述符,则字段查找将成功。声明的字段是字段查找的结果。

否则,字段查找将以递归方式应用于指定类或接口 C 的直接超接口。

否则,如果 C 具有超类 S,则字段查找将递归应用于 S。

否则,字段查找将失败。

换句话说,JVM 将解析为 。这就是为什么只需要加载类的原因。B.xA.xA


答案 2

因为实际上只有类需要加载。B.xA.xA


推荐