关于JAVA的初始化顺序问题:public class Element {
Element(String o){
System.err.println("==>"+o);
}
}
public class Test1 {
{
System.out.println("3");
} // 4.父类构造器
Test1() {
System.out.println("4");
} // 1.父类静态初始化块
static {
System.out.println("1");
}
public Element e=new Element("SupB");
public static Element es=new Element("StaticSupA");
}
public class Test2 extends Test1 {
Test2() {
System.out.println("6");
} // 2.子类静态初始化块
static {
System.out.println("2");
}
// 5.初始化块
{
System.out.println("5");
}
public Element e=new Element("SubB");
public static Element es=new Element("StaticSubA"); public static void main(String[] args) {
// 即使newTest2实例,静态块初始化也进行
System.gc();
new Test2();
}
}
我一直以为运行结果是:1
==>StaticSupA
2
==>StaticSubA
3
==>SupB
4
5
==>SubB
6
==================
上面的结果确实出来了,但是再运行,它又会是:1
2
==>StaticSupA
==>StaticSubA
3
==>SupB
4
5
==>SubB
6
==================
还会是这个:
1
==>StaticSupA
==>StaticSubA
2
3
==>SupB
==>SubB
4
5
6
=====================
这个怎么解释,难道是:先静态,后非静态。至于静态和非静态的初始化顺序,那是不确定的?或者说是随机的?

解决方案 »

  1.   

    分组:
    第一组:1;==>StaticSupA; 2; ==>StaticSubA.
    第二组:剩下的规则1:
    第一组(初始化时执行) > 第二组(创建对象时执行)
    表现为:静态初始化块 >  普通初始化块
            静态初始化块 >  构造方法
            静态变量     >  构造方法规则2:普通初始化块不依赖构造方法
    表现为:普通初始化块和构造方法无先后顺序注意,规则2出自本人推断,鉴于初始化过程没必要考虑语法逻辑自行思考 仅供参考
      

  2.   

    1
    ==>StaticSupA
    2
    ==>StaticSubA
    3
    ==>SupB
    4
    5
    ==>SubB
    6
    这个顺序比较符合常规解释!至于其它结果 可能是线程时间片影响的期待大牛解释!...
      

  3.   

    如果将 System.gc();语句注释掉的话,就会一直呈现如下打印信息
    // System.gc();  // 至于加上这条就会出现你的那种情况,俺也不明白为什么,望高人解答
    1
    ==>StaticSupA
    2
    ==>StaticSubA
    3
    ==>SupB
    4
    5
    ==>SubB
    6
      

  4.   

    public class Element {
        Element(String o){
            System.err.println("==>"+o);
        }
    }
    貌似是会受Element中的System.err.println的影响,如果也改成System.out.println,你加上System.gc()与不加上结果都是一样,而且结果都是符合我们正常理解逻辑的,输出结果:
    父类静态代码块static{}...
    父类静态类属性static Element...
    子类静态块static{}...
    子类静态类属性static Element...
    父类代码块{}...
    父类类属性Element....
    父类构造方法Test1()...
    子类代码块{}...
    子类类属性Element...
    子类构造方法Test()...
    对System.err.println(),疑惑ing...
      

  5.   


    果然是err的问题我都没发现用的是err害得我一直担心。。不过为何用err会出现随机的输出还要等待大牛
      

  6.   

    难道err是另外一个线程??????????
      

  7.   

    确实是因为err引起的,但这是为什么?
      

  8.   

    我测试过这个程序结果不对啊!而且在程序中这样语法没错误的吗?在一个程序中可以定义多个public类吗?能教教我吗?
      

  9.   

    有人发了信息给我,我才过来看看的。以后这种测试,就不要太依赖于System.out.println和System.err.println了。首先err和out就不是一个输出流,虽然默认情况最终都会输出到stdio上去,但由于不是同一个输出流,所以其最终输出到屏幕上的时间就是不可控的。
    另外,其实println本身也不是一个线程安全的方法,也就是不能保证输出先后顺序跟执行顺序绝对一致,不过因为本案例中只有主线程这1个所以倒也没这方面的问题。
      

  10.   

    这是结论吗
    我刚说第一组(初始化时执行) >  第二组
    先说初始化部分,请问你怎么保证父类静态代码块static{}...早于子类静态块static{}...
    你也不能保证父类静态类属性static Element..早于子类静态类属性static Element...
    这两点都没办法确定下面第二组(初始化部分)
    我刚才也说了不确定"普通初始化块和构造方法无先后顺序"
    但在本例中LZ用输出流来表达顺序,那只能说在本例中"普通初始化块和构造方法无先后顺序"成立了
    所以强烈质疑这个顺序
    父类代码块{}...
    父类类属性Element....
    父类构造方法Test1()...
    子类代码块{}...
    子类类属性Element...
    子类构造方法Test()...