day43-反射02( 三 )


静态加载的类,即使没有用到也会加载,并且进行语法的校验
  • 动态加载:运行时加载相关的类,如果运行时不用该类,即使不存在该类,也不会报错,降低了依赖性
  • 类加载的时机:
    1. 当创建对象时(new)//静态加载
    2. 当子类被加载时 //静态加载
    3. 调用类中的静态成员时 //静态加载
    4. 通过反射 //动态加载
  • 例子:静态加载和动态加载
    import java.lang.reflect.*;import java.util.*;public class classLoad_ {public static void main(String[] args) throws Exception {Scanner scanner = new Scanner(System.in);System.out.println("请输入key");String key = scanner.next();switch (key) {case "1":Dog dog = new Dog();//静态加载,依赖性很强dog.cry();break;case "2"://反射 -->动态加载Class cls = Class.forName("Person"); //加载Person[动态加载]Object o = cls.newInstance();Method m = cls.getMethod("hi");m.invoke(o);System.out.println("ok");break;default:System.out.println("do nothing...");}}}//因为new Dog()是静态加载,因此必须编写Dog//Person类是动态加载,所以即使没有编写Person类也不会报错,只有当动态加载该类时,(有问题)才会报错class Dog{public void cry(){System.out.println("小狗在哭泣..");}}在没有编写Dog类时,即使在switch选择中,不一定会运行到new dog对象的case1,但是程序仍然报错了 , 因为静态加载的类,即使没有用到,也会加载,并且进行语法的校验
    day43-反射02

    文章插图
    在编写了Dog类对象后,可以看到编译通过:
    day43-反射02

    文章插图
    运行程序:可以看到,即使没有编写Person类 , 但是运行时没有用到,就不会报错
    day43-反射02

    文章插图
    使用到Person类,报错:(运行时加载)
    day43-反射02

    文章插图
    6.类的加载过程
    • 类加载过程图

    day43-反射02

    文章插图
    • 类加载各阶段完成的任务
      • 加载阶段:将类的class文件读入内存 , 并为之创建一个java.lang.Class对象 。此过程由类加载器完成 。
      • 连接阶段:将类的二进制数据合并到jre中
      • 初始化阶段:JVM负责对类进行初始化,这里主要是指静态成员
    6.1.1加载阶段
    day43-反射02

    文章插图
    JVM 在该阶段的主要目的是,将字节码从不同的数据源(可能是class文件,也可能是jar包 , 甚至网络)转化为二进制字节流加载到内存中,并声称一个代表该类的java.lang.Class对象
    day43-反射02

    文章插图
    6.1.2连接阶段-验证
    day43-反射02

    文章插图
    1. 目的是为了确保Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全
    2. 包括:文件格式验证(是否以 魔数 oxcafebabe开头)、元数据验证、字节码验证和符号引用验证

    day43-反射02

    文章插图
    1. 可以考虑使用 -Xverify:none 参数关闭大部分的类验证措施,缩短虚拟机类加载的时间
    6.1.3连接阶段-准备
    day43-反射02

    文章插图
    JVM会在该阶段对静态变量,分配内存并默认初始化(对应的数据类型的默认初始值,如0,0L,null,false等) 。这些变量所使用的内存都将在方法区中进行分配
    例如:
    package li.reflection.classload_;//我们说明一个类加载的链接阶段-准备public class ClassLoad02 {public static void main(String[] args) {}}class A {//属性-成员变量-字段//一个类加载的链接阶段中的准备阶段 属性是如何处理的//1. n1 是实例变量,不是静态变量,因此在准备阶段,是不会分配内存的//2. n2 是静态变量,分配内存 n2 , 且默认初始化为 0,而不是20//3. n3 是static final , 是常量,它和静态变量不一样,因为一旦赋值就不变,n3 = 30public int n1 = 10;public static int n2 = 20;public static final int n3 = 30;}6.1.4连接阶段-解析
    day43-反射02

    推荐阅读