Java类的加载及初始化
每个类的编译代码都存在于它自己的独立文件中,该文件在需要使用该程序代码时才会被加载。通常有以下三种加载情况:
(1) 访问了子类的静态变量或静态方法:仅对类的静态变量,静态块执行初始化操作,并仅初始化一次。[代码1]
初始化的顺序:父类的静态变量,静态块 --> 子类的静态变量,静态块 (静态域仅初始化一次)
(2) 通过构造器创建了子类的第一个对象[new XX()]:不仅对类的静态变量,静态块执行初始化操作, 还会对实例变量,块执行初始化操作。[代码2]
初始化的顺序:父类的静态变量,静态块 --> 子类的静态变量,静态块 --> 父类的实例变量,块 --> 父类的构造器 --> 子类的实例变量,块 --> 子类的构造器 (静态域仅初始化一次)
(3) 反射: 使用[Class.forName()]时同(1),使用[newInstance()]时同(2)。[代码3]
注意事项:
(A1) 子类访问父类的静态域,子类只会初始化父类的静态变量,静态块。不会初始化自己的。
(A2) 仅仅初始化一个数组对象是不会对此对象初始化的。
[代码1]
1 public static void main(String[] args) throws Exception { 2 ParentClass.parentStaticMethod(); 3 }
output:
Call: ParentClass >> parentField2
Call: ParentClass >> static block
Call: ParentClass >> parentStaticMethod
[代码2]
1 public static void main(String[] args) throws Exception { 2 new ChildClass(); 3 }
output:
Call: ParentClass >> parentField2
Call: ParentClass >> static block
Call: ChildClass >> childField2
Call: ChildClass >> static block
Call: ParentClass >> parentField1
Call: ParentClass >> block
Call: ParentClass >> constructor
Call: ChildClass >> childField1
Call: ChildClass >> block
Call: ChildClass >> constructor
[代码3]
1 public static void main(String[] args) throws Exception { 2 System.out.println("--execute: forName----"); 3 Class<?> clazz = Class.forName("ChildClass"); 4 System.out.println("--execute: newInstance----"); 5 clazz.newInstance(); 6 }
output:
--execute: forName----
Call: ParentClass >> parentField2
Call: ParentClass >> static block
Call: ChildClass >> childField2
Call: ChildClass >> static block
--execute: newInstance----
Call: ParentClass >> parentField1
Call: ParentClass >> block
Call: ParentClass >> constructor
Call: ChildClass >> childField1
Call: ChildClass >> block
Call: ChildClass >> constructor
ParentClass.java
1 public class ParentClass { 2 3 String parentField1 = parentMethod1(); 4 5 static String parentField2 = parentMethod2(); 6 7 { 8 System.out.println("Call: ParentClass >> block"); 9 } 10 11 static { 12 System.out.println("Call: ParentClass >> static block"); 13 } 14 15 ParentClass() { 16 System.out.println("Call: ParentClass >> constructor"); 17 } 18 19 String parentMethod1() { 20 System.out.println("Call: ParentClass >> parentField1"); 21 return null; 22 } 23 24 static String parentMethod2() { 25 System.out.println("Call: ParentClass >> parentField2"); 26 return null; 27 } 28 29 static String parentStaticMethod() { 30 System.out.println("Call: ParentClass >> parentStaticMethod"); 31 return null; 32 } 33 }
ChildClass.java
1 public class ChildClass extends ParentClass { 2 3 String childField1 = childMethod1(); 4 5 static String childField2 = childMethod2(); 6 7 { 8 System.out.println("Call: ChildClass >> block"); 9 } 10 11 static { 12 System.out.println("Call: ChildClass >> static block"); 13 } 14 15 ChildClass() { 16 System.out.println("Call: ChildClass >> constructor"); 17 } 18 19 String childMethod1() { 20 System.out.println("Call: ChildClass >> childField1"); 21 return ""; 22 } 23 24 static String childMethod2() { 25 System.out.println("Call: ChildClass >> childField2"); 26 return ""; 27 } 28 29 static String childStaticMethod() { 30 System.out.println("Call: ChildClass >> childStaticMethod"); 31 return null; 32 } 33 }