spring学习系列(二)- 反射的使用与原理

            反射其实是间接调用,这样有什么好处呢,其实也是动态编译,不用改变源码。java的反射机制就是增加程序的灵活性,避免将程序写死到代码里。动态配置 联合XML,就可以

             java允许我们间接对Class的对象实例操作,Class文件有类装载器装载后,在JVM中形成一份描述Class的结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等。实际就是 间接调用
下面通过一个例子来将下反射机制的流程:

ReflectTest.java


public class ReflectTest {
​
​
    public static Car initCarByReflect() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
         //初始化类加载器
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        Class clazz = classLoader.loadClass("com.spring.demo.Car");
​
        //获取类构造器
        Constructor constructor = clazz.getDeclaredConstructor((Class[])null);
        Car car = (Car) constructor.newInstance();
​
        //反射放设置属性
​
        Method setBrand = clazz.getMethod("setBrand",String.class);
        setBrand.invoke(car, "宝马车");
​
        Method setColor = clazz.getMethod("setColor",String.class);
        setColor.invoke(car, "颜色");
​
        Method setMaxSpeed = clazz.getMethod("setMaxSpeed",Integer.class);
        setMaxSpeed.invoke(car, 12);
​
        return car;
    }
​
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        Car car = initCarByReflect();
        System.out.println(car.toString());
    }
​
}

Car.java

public class Car {
​
     private String brand;
     private String color;
     private int maxSpeed;
​
    public Car(String brand, String color, int maxSpeed) {
        this.brand = brand;
        this.color = color;
        this.maxSpeed = maxSpeed;
    }
​
    public Car() {
    }
​
​
    public String getBrand() {
        return brand;
    }
​
    public void setBrand(String brand) {
        this.brand = brand;
    }
​
    public String getColor() {
        return color;
    }
​
    public void setColor(String color) {
        this.color = color;
    }
​
    public int getMaxSpeed() {
        return maxSpeed;
    }
​
    public void setMaxSpeed(Integer maxSpeed) {
        this.maxSpeed = maxSpeed;
    }
​
    @Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + '\'' +
                ", color='" + color + '\'' +
                ", maxSpeed=" + maxSpeed +
                '}';
    }
}

运行后结果

spring学习系列(二)- 反射的使用与原理_第1张图片

类加载器工作流程

类加载器是寻找类的字节码文件并构造出类在JVM 内部表示的组件
装入的流程如下:

  1. 装载: 查找和导入Class文件
  2. 链接: 执行校验 准备和解析步骤 其中解析步骤是可以选择的
    1. 校验: 检查载入Class文件数据的正确性
    2. 准备:给类的静态变量分配
    3. 解析 :将符号引用转成直接引用
  3. 初始化:对类的静态变量 静态代码块执行初始化工作

其实有三个类加载器,然后他们采用的是双亲委派机制 这也是面试的时候会常问的问题,还有双亲委派机制有什么好处?如何打破? 可以看我的面试题目系列。在虚拟机提供了3种类加载器,引导(Bootstrap)类加载器、扩展(Extension)类加载器、系统(System)类加载器(也称应用类加载器)   要查看类的关系可以用一段代码测试。

ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
System.out.println("classLoader is" + classLoader);
System.out.println("classLoader is" + classLoader.getParent());
//ClassLoader 是根加载器获取不到 句柄的
System.out.println("classLoader is" + classLoader.getParent().getParent());

spring学习系列(二)- 反射的使用与原理_第2张图片

 

可见依次的 AppClassLoader->ext->Bootstrap  为什么最上层父类BootStrap获取不到呢 ,那是因为前两个继续的它是用java实现的,BootStrap是C++实现的 故而获取不到

你可能感兴趣的:(java)