类加载

来源:互联网 发布:网络统考app 编辑:程序博客网 时间:2024/06/04 21:28

类加载主要包括5个步骤(加载、验证、准备、解析和初始化)

加载:加载需要完成3件事

1:首先是通过一个类的全限定名称来获取定义此类的二进制字节流

2:将转化的二进制字节流代表的静态存储结构转化为 方法区  的运行时数据结构

3::在内存中生成一个代表这个类的 java.lang.Class对象(HotSpot虚拟机中,这个对象 放在了 方法区而不是堆中)

验证:主要是为了保证Class文件的字节流符合虚拟机的要求,并且不会危害虚拟机自身的安全。主要包括 文件格式的验证、元数据的验证、字节码的验证符号引用的验证

准备:主要是在方法区为类变量(static修饰)分配内存并为类变量设置初始值(int 默认为 0、double 默认为 0.0d 、 float默认为 0.0f、 refrence 默认为 null、boolean 默认为false)

解析:主要包括 类或接口的解析、 字段的解析 、类方法的解析 、接口方法解析

初始化:主要是执行 静态代码块中的代码以及为静态变量赋值(为在准备阶段分配内存的变量赋值 程序员指定的值)


上面介绍了类加载、那么子类和父类 类加载的顺序是怎样的呢?我们通过代码验证下


public class A {public static String a = "a";static{System.out.println("A的静态代码块被执行了");}public A(){System.out.println("A的构造函数被执行了");}}public class B extends A{public static String b = "b";static{System.out.println("B的静态代码块被执行了");}public B(){System.out.println("B的构造函数被执行了");}}public class Test {public static void main(String[] aStrings) throws InstantiationException, IllegalAccessException{System.out.println(B.a);//A的静态代码块被执行了   a//System.out.println(B.b);//A的静态代码块被执行了   B的静态代码块被执行了   b//System.out.println(B.class.newInstance().b);//A的静态代码块被执行了   B的静态代码块被执行了   A的构造函数被执行了   B的构造函数被执行了  b} }

在main方法中我写了三行代码 ,每行代码执行的结果 都写在了对应的代码后面

第一行,我调用了 B.a 结果是执行了 A 类的静态代码块以及为 a 赋值为 “a” ,为什么没有执行B的静态代码块呢?因为 a属性是A类的属性,对于类变量的调用只会触发该类变量所属类的 类加载因此并不会触发B类的 类加载。


第二行,我调用了B.b  结果是执行了 A 类的静态代码块、为 a 赋值为 “a”  、B 类的静态代码块以及为 b 赋值为 “b” 说明子类在类加载之前必须保证父类已经进行了类加载 


第三行,与第二行相比,在进行了类加载的基础上 有触发了 类对象的实例化(通过 new 以及反射可以触发) ,所以A B两类的构造函数也被执行了并且执行顺序是 先父 后子





原创粉丝点击