详解Java中类的加载与其初始化
从未止步.. 人气:0java内存分析
类加载的过程
类的加载与ClassLoader的理解
类的初始化
package Collections; public class text1 { public static void main(String[]args){ A a=new A(); System.out.println(A.m); } } class A{ static { System.out.println("A类静态代码块初始化"); m=300; } static int m=100; public A(){ System.out.println("A类的无参构造初始化"); } }
输出:
A类静态代码块初始化
A类的无参构造初始化
100
为什么最终输出的m值为100呢?
分析如下:
首先类进行加载和链接,如下所示:
注:在链接阶段的准备工作时,编译器会为类变量赋默认值为0,即此时的m为0
链接完毕后进行类的初始化,这一过程将会执行类构造器()方法,将类中所有类变量的赋值语句以及静态代码块中的语句收集和合并:
<clinit>() { System.out.println("A类静态代码块初始化"); m=300; m=100; }
第二条m的赋值语句,覆盖了第一条的300,因此最终输出为100
会发生类的初始化的场景
类的主动引用(一定会发生类的初始化)
类的主动引用
package Collections; import static Collections.Son.m; public class text1 { static { System.out.println("Main类被加载"); } public static void main(String[]args) throws ClassNotFoundException { Son son=new Son(); } } class Father{ static int a=10; static{ System.out.println("Father类被加载"); } } class Son extends Father{ static { System.out.println("子类被加载"); m= 300; } static int m =100; static final int M = 1; }
输出:
Main类被加载
Father类被加载
子类被加载
反射也会产生主动引用
package Collections; import static Collections.Son.m; public class text1 { static { System.out.println("Main类被加载"); } public static void main(String[]args) throws ClassNotFoundException { Class.forName("Collections.Son"); } } class Father{ static int a=10; static{ System.out.println("Father类被加载"); } } class Son extends Father{ static { System.out.println("子类被加载"); m= 300; } static int m =100; static final int M = 1; }
输出:
Main类被加载
Father类被加载
子类被加载
类的被动引用(不会发生类的初始化)
当访问一个静态域时,只有真正声明这个域的类才会被初始化,如:当通过子类引用父类的静态变量,不会导致子类初始化。
举例:
package Collections; import static Collections.Son.m; public class text1 { static { System.out.println("Main类被加载"); } public static void main(String[]args) throws ClassNotFoundException { System.out.println(Son.a); } } class Father{ static int a=10; static{ System.out.println("Father类被加载"); } } class Son extends Father{ static { System.out.println("子类被加载"); m= 300; } static int m =100; static final int M = 1; }
输出:
Main类被加载
Father类被加载
10
通过数组定义类引用,不会触发此类的初始化
举例:
package Collections; import static Collections.Son.m; public class text1 { static { System.out.println("Main类被加载"); } public static void main(String[]args) throws ClassNotFoundException { Son[] arry=new Son[5]; } } class Father{ static int a=10; static{ System.out.println("Father类被加载"); } } class Son extends Father{ static { System.out.println("子类被加载"); m= 300; } static int m =100; static final int M = 1; }
输出:
Main类被加载
引用常量不会触发此类的初始化(常量在链接阶段就存入调用类的常量池中了)
举例:
package Collections; import static Collections.Son.m; public class text1 { static { System.out.println("Main类被加载"); } public static void main(String[]args) throws ClassNotFoundException { System.out.println(Son.M); } } class Father{ static int a=10; static{ System.out.println("Father类被加载"); } } class Son extends Father{ static { System.out.println("子类被加载"); m= 300; } static int m =100; static final int M = 1; }
输出:
Main类被加载
1
加载全部内容