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.");
        }
    }

问题:为什么输出将是:“x”。 但不是:“内部Bx”


Bx的引用发出以下字节码:

getstatic       #3   <Field int B.x>

根据Java虚拟机规格

Java虚拟机指令anewarray,checkcast,getfield命令,getstatic,的instanceof,invokedynamic,invokeinterface,invokespecial,invokestatic,invokevirtual,最不发达国家,ldc_w,multianewarray,新,putfield,并putstatic做出运行时间常量池中的符号引用 。 执行任何这些指令都需要解析其符号引用

所以JVM应该解析Bx符号引用 。 现场分辨率是这样指定的:

要解析从D到类或接口C中字段的未解析符号引用,必须首先解析由字段引用给出的对C的符号引用(第5.4.3.1节)。

...

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

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

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

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

否则,字段查找失败。

换句话说,JVM会将Bx解析为Ax 。 这就是为什么只有A类需要加载。


因为Bx实际上是Ax所以只需要加载A类。


Java SE 7版的Java语言规范的§12.4“类和接口的初始化”指定:

类的初始化包括执行其static初始化程序以及在类中声明的静态字段(类变量)的初始化程序。

[...]

static字段(第8.3.1.1节)的引用只会初始化实际声明它的类或接口,即使它可能通过子类名称,子接口或实现接口的类来引用。

因此,尽管-违背了上面的一些答案的说法-类B确实有被加载,以确定Bx是声明在A ,类B未初始化(即,它的static初始化没有实际运行),直到你做一些更具体的B

链接地址: http://www.djcxy.com/p/3477.html

上一篇: java static initialization with inheritance

下一篇: Why does Java have transient fields?