在Java中,main方法之后的那些语句的初始化顺序是什么

我了解到初始化顺序的原则是:

  1. 超类首先(在这种情况下不在这里讨论)
  2. 静态变量声明和静态初始化块按出现顺序排列
  3. 实例变量声明和静态初始化块按出现顺序排列
  4. 构造函数

但我仍然对此代码的输出感到困惑:

public class Test1 { static { add(2); } static void add (int num) { System.out.println(num + " "); } public Test1() { add(5); System.out.println("Constructor!"); } static { add(4); } { add(6); } static { new Test1(); } { add(8); } public static void main(String[] args) { System.out.println("Main method!"); add(10); } { add(11); } static { add(12); } } 

结果是:

 2 4 6 8 11 5 Constructor! 12 Main method! 10 

如果没有add(10)的陈述; 加(11); 加(12); 我完全可以理解。 你能解释一下这3个语句的初始化顺序吗?

1)没有如下名称的块称为“ 实例初始化器 ”,只有在创建新对象时才会调用它,如DefaultConstructor或noArg构造函数。

 { add(11); } 

2)在上面的代码中,你有静态块在类加载本身首先被调用 ), 实例初始化器在创建对象时被调用 ), 显式DefaultConstructor在创建对象时被调用,但记住始终优先实例初始化器) )和最后的主要方法。

3)现在让我们分析你的代码,

第一次电话:

 static { add(2); //print 2 } 

第二个电话:

 static { add(4); // print 4 } 

第3个电话:

 static { new Test1(); // Here Object is getting created so all Instance Initialzer will be called first in a sequential manner. } 

第四个电话:

 { add(6); // print 6 } 

第5个电话:

 { add(8); // print 8 } 

第6次电话:

 { add(11); // print 11 } 

第7次调用:在Instance Initializer之后,将调用Explicit Default Constructor。

 public Test1() { add(5); // print 5 System.out.println("Constructor!"); // print Constructor! } 

第8次调用:再次调用最后一个静态块。

 static { add(12); // print 12 } 

第9次调用:最后将调用main方法

 public static void main(String[] args) { System.out.println("Main method!"); // print Main method! add(10); // print 10 } 

静态初始化程序是第一个,所以你得到

 2 4 

但是在下一个静态初始化程序中,您调用Test1.class的新实例,因此触发实例初始化程序,在它们之后触发构造函数,并得到:

 6 8 11 5 Constructor! 

之后调用其余的静态初始化程序。 所以:

 12 

最后一个是主要方法:

 Main method! 10 

我觉得你很困惑,因为(12)之前(主要方法 – 10)

发生这种情况是因为在最后但是其他初始化顺序调用的main方法是明确的

在Java中,对于一个类, 所有静态初始化器在所有构造函数之前按顺序(从顶部到底部)执行。 {}中的术语被添加到构造函数中,这些不是静态初始化器(请参阅http://docs.oracle.com/javase/tutorial/java/javaOO/initial.html )。

那么Test1的实例1:

 static { add(2); } ... static { add(4); } 

然后,在静态块内部有一个Test1的构造函数。 它被调用,因此实例成员被初始化,因为之前的静态初始化器已被调用:

 { add(6); } ... { add(8); } ... { add(11); } 

之后,调用构造函数中的下一个操作:

 add(5); 

然后我们在第一个实例中返回以调用最后一个静态initiazer:

 static { add(12); } 

最后,如果完全初始化了类,那么调用main方法:

 public static void main(String[] args) { System.out.println("Main method!"); add(10); } 

所以,输出:

 2 4 6 8 11 5 Constructor! 12 Main method! 10 

无论@DontPanic回答什么都是正确的,我要强调的要点是源代码中代码块的顺序(从上到下)也很重要 ,你可以从Java doc看这里 。

一个类可以有任意数量的静态初始化块,它们可以出现在类体中的任何位置。 运行时系统保证按照它们在源代码中出现的顺序调用静态初始化块。