1、执行顺序
1.1、一个类中的初始化顺序
类内容(静态变量、静态初始化块) => 实例内容(变量、初始化块、构造器)
1.2、两个具有继承关系类的初始化顺序
父类的(静态变量、静态初始化块)=> 子类的(静态变量、静态初始化块)=> 父类的(变量、初始化块、构造器)=> 子类的(变量、初始化块、构造器)
示例如下:(结果见注释)
1 class A { 2 public A() { 3 System.out.println("Constructor A."); 4 } 5 6 { 7 System.out.println("Instance Block A."); 8 } 9 static {10 System.out.println("Static Block A.");11 }12 13 public static void main(String[] args) {14 new A();/*15 * Static Block A. Instance Block A. Constructor A.16 */17 }18 }19 20 class B extends A {21 public B() {22 System.out.println("Constructor B.");23 }24 25 {26 System.out.println("Instance Block B.");27 }28 static {29 System.out.println("Static Block B.");30 }31 32 public static void main(String[] args) {33 new A();/*34 * Static Block A. Static Block B. Instance Block A. Constructor A.35 */36 System.out.println();37 new B();/*38 * Instance Block A. Constructor A. Instance Block B. Constructor B.39 */// 静态成员和静态初始化块只会执行一次。40 }41 }
2、对变量值的影响
一个变量,若显示初始化、初始化块对该变量赋值、构造方法对该变量赋值同时存在,则变量最终值如何确定?按1节中所述的执行顺序确定。
这里考虑初始化块在变量定义之前的情形,此时会造成迷惑。
初始化块可以对在它之后定义的变量赋值,但不能访问(如打印)。如:
1 static {2 a = 3;3 // int b=a;//Cannot reference a field before it is defined4 // System.out.println(a);//Cannot reference a field before it is defined5 }6 static int a = 1;
“对变量值的影响”是指 对变量赋值的初始化块位于变量定义之前 时,变量的最终值根据变量定义时是否显示初始化而会有不同结果(若初始化块位于变量定义之后,那么变量的值显然很容易就确定了,不会造成迷惑)。如:
1 class Test { 2 static { 3 a = 3; 4 // int b=a;//Cannot reference a field before it is defined 5 // System.out.println(a);//Cannot reference a field before it is defined 6 b = 3; 7 } 8 static int a = 1; 9 static int b;10 11 public static void main(String[] args) {12 System.out.println(a);//113 System.out.println(b);//314 }15 }
判断方法:
显示初始化内部隐含 定义变量和对变量进行赋值的初始化块两部分,所以初始化块和显示初始化哪个在后变量的最终值就是该值。
更多示例:
1:
1 class C { 2 3 static { 4 a = 2; 5 b = 2; 6 } 7 static int a; 8 static int b = 1; 9 10 public C() {11 e = 3;12 }13 14 {15 c = 2;16 d = 2;17 e = 2;18 }19 int c;20 int d = 1;21 int e = 1;22 23 public static void main(String[] args) {24 System.out.println(C.a);//225 System.out.println(C.b);//126 System.out.println(new C().c);//227 System.out.println(new C().d);//128 System.out.println(new C().e);//329 }
2:
1 class C { 2 public C() { 3 } 4 5 { 6 a = 3; 7 } 8 static { 9 a = 2;10 }11 static int a;12 static int b;13 14 public static void main(String[] args) {15 System.out.println(C.a);// 216 System.out.println(new C().a);// 317 System.out.println(C.b);// 018 }19 }
3:
1 class C { 2 // 以下关于静态初始化的 3 static { 4 a = 2; 5 } 6 static int a = 1; 7 static int b = 1; 8 static { 9 b = 2;10 c = 2;11 }12 static int c;13 14 {15 d = 2;16 }17 int d = 1;18 int e = 1;19 {20 e = 2;21 f = 2;22 }23 int f;24 25 public static void main(String[] args) {26 System.out.println(C.a);// 127 System.out.println(C.b);// 228 System.out.println(new C().c);// 229 System.out.println(new C().d);// 130 System.out.println(new C().e);// 231 System.out.println(new C().f);// 232 }33 }
3、总结
执行顺序:
1、类内容(静态变量、静态初始化块) => 实例内容(变量、初始化块、构造器)
2、父类的(静态变量、静态初始化块)=> 子类的(静态变量、静态初始化块)=> 父类的(变量、初始化块、构造器)=> 子类的(变量、初始化块、构造器)
初始化块可以对在它之后定义的变量赋值,但不能访问(如打印)。
变量最终值:一个变量,若显示初始化、初始化块对该变量赋值、构造方法对该变量赋值同时存在,则变量最终值如何确定:
1、按执行顺序
2、若对变量赋值的初始化块在变量定义前时:若变量显示初始化了则最终为显示初始化值,否则为初始化块的赋值。
注:凡事总有例外,实例初始化也可能位于类静态初始化前,示例:
public class StaticTest { public static void main(String[] args) { staticFunction(); } static StaticTest st = new StaticTest(); static { System.out.println("1"); } { System.out.println("2"); } StaticTest() { System.out.println("3"); System.out.println("a=" + a + ",b=" + b); } public static void staticFunction() { System.out.println("4"); } int a = 110; static int b = 112;}结果如下:23a=110,b=014