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、对变量值的影响
2.1、问题
Java中一个变量的初始化与初始化块对该变量的赋值同时存在时变量的最终值如何确定?特别是初始化块在变量定义之前甚至静态初始化块和实例初始化块都对该变量进行赋值时更迷惑人。如对于如下示例,输出的值分别为多少?(已给出):
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);//2 25 System.out.println(C.b);//1 26 System.out.println(new C().c);//2 27 System.out.println(new C().d);//1 28 System.out.println(new C().e);//3 29 }
2.2、分析
成员变量(类变量、实例变量)的 初始化块赋值 及 变量定义 同时存在时变量的值的确定。包含如下几种情况:
情况1、静态变量定义 及 静态初始化块改变该变量值 同时存在时变量的最终值。
情况2、实例变量定义 及 实例初始化块改变该变量 同时存在时变量的最终值。
情况3、或上述两种同时改变一个变量 时变量的最终值。
若初始化块在变量定义之后,则易知值为初始化块里的赋值,因此这里考虑若初始化块在变量定义之前的情形。
2.3、结论
(考虑 对变量赋值的初始化块在变量定义之前 的情形)
1、对于静态操作和实例操作同时存在的情况(情况3),根据上节所述的执行顺序确定值;
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);// 2 16 System.out.println(new C().a);// 3 17 System.out.println(C.b);// 0 18 } 19 }
3、若定义时显示地初始化了,即情况1、2,其处理方法一样:
变量定义时进行显式初始化实际上内部隐含 定义及初始化块对之进行赋值 两个过程,因此若还包含初始化块代码,则Java会将它们合并成一个处理,所以结论是显式初始化和初始化块哪个在后值就是哪个。如:
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);// 1 27 System.out.println(C.b);// 2 28 System.out.println(new C().c);// 2 29 System.out.println(new C().d);// 1 30 System.out.println(new C().e);// 2 31 System.out.println(new C().f);// 2 32 } 33 }
时间: 2024-10-16 09:33:24