请教一个变量初始化顺序问题?

malie0 2013-05-09
程序:
public class Dog {
    static int i = 10;
    static Poddle p = new Poddle();

    public static void main(String args[]){
        System.out.println("exe main method!   i:"+i+"  p:"+p);
    }

    static {
        System.out.println("exe static block in Dog!");
    }
    {
        System.out.println("exe common block in Dog!");
    }

    public Dog() {
        System.out.println("exe Dog contructor!");
    }

    public String toString() {
        return "exe toString() in Dpg!";
    }

    static class Poddle extends Dog {
        static {
            System.out.println("exe static block in Poddle!");
        }
        {
            System.out.println("exe common block in Poddle!");
        }

        public Poddle() {
            System.out.println("exe Poddle contructor!");
        }

        public static void staticMethod() {
            System.out.println("exe static method in Poddle!");
        }

        public String toString() {
            return "exe toString() in Poddle!";
        }
    }
}

运行结果:
exe static block in Poddle!
exe common block in Dog!
exe Dog contructor!
exe common block in Poddle!
exe Poddle contructor!
exe static block in Dog!
exe main method!   i:10  p:exe toString() in Poddle!

请教为什么Dog类的静态块不是一开始就执行而是到main方法运行前才执行,不是子类初始化前先要初始化父类吗?
RednaxelaFX 2013-05-09
因为您的代码里Dog类的<clinit>()V里触发了Poddle类的初始化,而当JVM要初始化Poddle类时发现它的父类Dog正在初始化过程中,就不会递归调用进Dog的静态初始化器<clinit>()V。

Dog.<clinit>()V的代码大致是这样:
i = 10;
p = new Poddle(); // 这里触发了Poddle类的初始化
System.out.println("exe static block in Dog!");

留意这些代码的顺序,跟源码里所有跟Dog类的静态初始化相关的代码的顺序一致。

您代码里所谓"common block"实际上不是common的,而会被收集为实例初始化器<init>()V的一部分。
Dog.<init>()V的代码大致是这样:
System.out.println("exe common block in Dog!");  // 匿名初始化块按源码里的顺序收集起来之后,放在构造器之前
// 然后是构造器里的代码
System.out.println("exe Dog contructor!");
malie0 2013-05-09
RednaxelaFX 写道
因为您的代码里Dog类的<clinit>()V里触发了Poddle类的初始化,而当JVM要初始化Poddle类时发现它的父类Dog正在初始化过程中,就不会递归调用进Dog的静态初始化器<clinit>()V。

Dog.<clinit>()V的代码大致是这样:
i = 10;
p = new Poddle(); // 这里触发了Poddle类的初始化
System.out.println("exe static block in Dog!");

留意这些代码的顺序,跟源码里所有跟Dog类的静态初始化相关的代码的顺序一致。

您代码里所谓"common block"实际上不是common的,而会被收集为实例初始化器<init>()V的一部分。
Dog.<init>()V的代码大致是这样:
System.out.println("exe common block in Dog!");  // 匿名初始化块按源码里的顺序收集起来之后,放在构造器之前
// 然后是构造器里的代码
System.out.println("exe Dog contructor!");

原来是这样,能得到大大的指点真是太高兴了。我主要的疑问就是递归调用初始化的问题,自己猜测也可能是因为父类正在初始化所以就不递归调用了只是一直找不到相关的文档说明来证明,现在证实了我的想法,请问哪里能找到有关这个问题的文档说明?
RednaxelaFX 2013-05-09
malie0 写道
原来是这样,能得到大大的指点真是太高兴了。我主要的疑问就是递归调用初始化的问题,自己猜测也可能是因为父类正在初始化所以就不递归调用了只是一直找不到相关的文档说明来证明,现在证实了我的想法,请问哪里能找到有关这个问题的文档说明?

JVM规范里讲类初始化的地方写得很清楚。请看几天前的一帖里引用的JVM规范的5.5小节里的第3步,那个就是递归初始化检测:http://hllvm.group.iteye.com/group/topic/37682#post-244280
Global site tag (gtag.js) - Google Analytics