Java--反射--类加载
- 基本说明
-
package com.model.Class; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Scanner; /** * @Description:测试类 * @Author: 张紫韩 * @Crete 2021/6/28 22:17 * 演示动态加载和静态加载 */ public class ClassDemo05 { /** * 静态加载的类,必须存在,不然会在编译的阶段就会报错 * 而动态加载的类,在编译阶段,类可以不存在也依然不会报错。只有执行到她的时候才会报错,找不到类 * */ public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException { Scanner scanner = new Scanner(System.in); System.out.println("请输入"); String key=scanner.next(); switch (key){ case "1": //静态加载,在编译的时候会对Dog类进行加载 // new Dog()----->静态加载 依赖性强 Dog dog = new Dog(); dog.m1(); break; case "2": //动态加载,子啊编译的时候不会对类进行加载,只有当执行到这个语句的时候才会进行Class类的加载 //动态加载也叫延迟加载,减小依赖 // 反射-----》动态加载 依赖性弱 Class<?> aClass = Class.forName("com.model.Class.Person"); Object o = aClass.newInstance(); Method method = aClass.getMethod("m2"); method.invoke(o); break; default: System.out.println("do nothing"); } } } class Dog{ public void m1(){ System.out.println("hello-dog"); } } class Person{ public void m2(){ System.out.println("hello-person"); } }
-
类加载流程图
-
加载和连接是由JVM虚拟机完成的,而初始化是由我们程序员控制的 ,方法区中放的是 某个类的字节码二进制数据文件,堆中存放的 是某个类的class类对象
-
-
类加载的五个阶段
-
-
package com.model.Class; /** * @Description:测试类 * @Author: 张紫韩 * @Crete 2021/6/28 23:23 * * 演示类类加载的各个阶段 * */ public class ClassDemo06 { public static void main(String[] args) throws ClassNotFoundException { // 加载阶段 Car car = new Car(); // 初始化阶段 /** * 1.加载B类,并生成B的Class对象 * 2.连接 num分配内存并初始化为0 * 3.初始化阶段: * 依次自动收集类中的所有的静态变量的赋值动作和静态代码块中的语句 * * clinit(){ 按顺序进行收集 * System.out.println("B()的静态代码块被执行"); * num=300; * static int num=100; * } * * 收集完之后会进行合并:相当于是这样的语句 * clinit(){ * System.out.println("B()的静态代码块被执行"); * static int num=100; * } * */ // new B();//类加载 ,会调用构造器 ,new 回到导致类的加载 System.out.println(B.num); //100 ,直接使用类中的静态属性也会导致类的加载 // 查看类加载的时候,是同步机制控制 /* 正是synchronized这种同步机制,才保证了只有一个Class对象 * synchronized (this) { 是线程同步的,不会造成多个线程同时加载累的时候保证了线程安全 ensureOpen(); textOut.write(s); textOut.flushBuffer(); charOut.flushBuffer(); if (autoFlush && (s.indexOf('\n') >= 0)) out.flush(); } } * */ B b = new B(); } } class A{ /** * 在类加载的 准备阶段 属性是如何处理的呢 * n1:是实例变量,不是静态变量,因此在准备极端不会分配内存 * n2:属于静态变量,分配内存 n2,并初始化为0 ,只分配空间并不进行赋值为20 * n3:属于常量,分配内存,并初始化为0,只分配内存,并不进行赋值为30 * * */ private int n1=10; private static int n2=20; private final int n3=30; } class B{ static{ System.out.println("B()的静态代码块被执行"); num=300; } static int num=100; public B(){ System.out.println("构造方法被执行"); } }