有以下简单java代码:public class Test {
static Test test = new Test("3");
// Test test2 = new Test("5"); static {
System.out.println("1");
} // static Test test = new Test("3"); {
System.out.println("2");
} Test(String s) {
System.out.println(s);
} public static void staticFunction() {
System.out.println("4");
} public static void main(String[] args) {
staticFunction();
}
}运行后打印结果:2
3
1
4当把上边代码的第9行注释去掉,第2行注释起来时,打印结果如下:1
2
3
4最后打印4没问题,问题在于为什么静态当前类的对象与静态块的顺序不同时,首先执行的代码顺序不同,导致结果不同呢???
希望大神可以详细讲解下,谢谢!还有一个额外的问题,当取消上边代码第 3 行的注释时,也就是创建两个当前类对象,一个静态一个非静态,运行后报栈溢出,应该是发生了递归调用,且递归没有出口,具体怎么一个顺序呢?望解答

解决方案 »

  1.   

    我现在 得知,第一部分:为什么是 2 3  1 4 。首先静态部分按照 顺序执行,
    1.先执行static Test test = new Test("3");  
    2.执行new 时,先执行代码快{} 此时为2
    3.在执行new Test(“3”),此时打印 3
    4.第一句静态部分执行完了,顺序执行静态代码块  打印1
    5.最后执行方法staticFunction(),打印4
    所以是2 3 1 4 。
    =======================================
    同理 ,注释第2行 ,还是顺序执行
    具体和上方一样
    ========================================
    关于你的报错   还未知,正在研究中
      

  2.   

    第一部分问题:
    在你所列举的例子中,  {}  优先于 static{}执行。注意如果是默认构造函数,static{}优先于{}执行。
    第二个问题:出错的原因
    (1)执行static Test test = new Test("3");时,会调用构造函数Test(String s) {}
    (2)调用构造函数Test(String s) {}时,会调用Test test2 = new Test("5");。 因为new对象,就得将对象的默认属性全部new好,除百把第三行改为 Test test2 = null就不会有这个问题了;
    (3)当调用Test test2 = new Test("5");。又会调用构造函数Test(String s) {}, 即程序又跳转到第(1)步。于是进入了死循环,直到StackOverflow
      

  3.   

    ============
    报错问题。
    1.由于test 是静态的变量 只是初始化一次,(因为静态变量  只在类加载的时候初始化一次) test 初始化时 会把test2(属于成员变量) 给实例化一次
    2.test2 再次实例化  又会实例化 test2  ,,,,此时由于test是静态的,只初始化一次,所以,此时test2进入循环
    3.最终导致 进入循环一直循环,引起栈溢出
    其实归根结底就是--实例变量是在实例化的时候进行声明初始化
      

  4.   

    首先初始化顺序,肯定是先初始化静态的static Test test = new Test("3"),静态初始化也是按照静态变量或者是静态代码块在成员变量的顺序执行,但是执行   static Test test = new Test("3")实例化对象的时候发现有一个代码块要执行,所以第一个数字是2,然后执行了构造函数打印出3,接着按照静态变量的初始化顺序执行到了静态代码块,打印出了1,最后到了main中执行方法staticFunction()打印出4。
          后面的一个问题看了前面两位的答案说实话我也没有搞懂,希望哪位可以解释的清楚点
      

  5.   

    1.改为默认构造函数,也是{}优于static{}
    2.Exception是因为无限初始化Test2造成的
      

  6.   

    关于这个报错的问题,我来解释下。
    首先把代码简化下,找到报错的真正原因:
    public class Test {
        Test test2 = new Test("5");
     
        Test(String s) {
            System.out.println(s);
        }
     
        public static void main(String[] args) {
            new Test("1");
        }
    }
    运行上面的代码,你会发现报错依然存在,所以这个报错和什么静态代码的无关,关键在于你陷入初始化的死循环了。
    当Test实例化时,会执行【Test test2 = new Test("5");】,这句话本身又要实例化一个Test,然后又要执行【Test test2 = new Test("5");】,然后你懂的。个人建议不要搞这些乌七八糟的代码,除非是程序实际遇到问题,否则劳民伤财未必能有成效。