• java 反射 类装载器


    前言:

         java语言允许通过程序化的方式间接对Class进行操作,Class文件由类装载器装载后,在jvm中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息,如构造函数,属性和方法等,

    java允许用户借由这个与Class相关的元信息对象间接调用Class对象的功能,这就为使用程序化方式操作Class对象开辟了途径。

    实例:

    下面一个Car类拥有两个构造函数,一个方法及三个属性

    package reflect;
    
    public class Car {
        private String brand; //品牌
        private String color; //颜色
        private int maxSpeed; //转速
    
        public Car(){}
    
        public Car(String brand, String color, int maxSpeed){
            this.brand = brand;
            this.color = color;
            this.maxSpeed = maxSpeed;
        }
        public void say(){
            System.out.println("brand:"+ brand + ", color:"+ color +", maxSpeed:"+ maxSpeed);
        }
    
    //set和get 方法省略

    一般情况下,我们会使用如下代码创建Car的实例:

    Car car = new Car();
    car.setBrand("红旗");

    这种是采用传统方式直接调用目标类,下面我们可以使用java反射机制以一种间接的方式操控目标类:

    public class ReflectTest {
    
        public static Car initByDefaultConst() throws Throwable{
            // 1. 通过类装载器获取Car类的对象
            ClassLoader loader = Thread.currentThread().getContextClassLoader();
            //使用全限定名来找class类
            Class clazz = loader.loadClass("reflect.Car");
    
            /*Class clazz = Class.forName("reflect.Car");*/  //另一种方式获取class
    
            // 2. 获取类的默认构造器对象并通过它实例化Car
            Constructor cons = clazz.getDeclaredConstructor((Class[])null);
            Car car = (Car)cons.newInstance();
    
            // 3. 通过反射方法设置属性
            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", int.class);
            setMaxSpeed.invoke(car,200);
            return car;
        }
        @Test
        public void test() throws Throwable{
            Car car = initByDefaultConst();
            car.say();
        }
    }

    运行以上程序,在控制台打印如下: brand:红旗, color:黑色, maxSpeed:200

    上述的程序只是用了很少的api,java反射包为我们提供了很多的方法,可以细查。

    其余扩展:

    类装载器ClassLoader的工作机制:

       类装载器就是寻找类的节码文件并构造出类在jvm内部表示对象的组件,在java中,类装载器把一个类装入jvm中,需要经过如下步骤:

            1.  装载:查找和导入Class文件

       2.  链接:执行校验,准备和解析步骤,其中解析步骤是可以选择的

        2.1. 校验:检查载入Class文件数据的正确性

        2.2. 准备: 给类的静态变量分配存储空间

        2.3. 解析:将符号引用转换成直接引用

       3.  初始化:对类的静态变量,静态代码块执行初始化工作

    JVM装载类使用 “全盘负责委托机制”,

    全盘负责”是指当一个ClassLoader装载一个类时(除非显式的使用另一个ClassLoader),该类所依赖及引用的类也由这个ClassLoader载入;

    委托机制”是指先委托父装载器寻找目标类,只有在找不到的情况下才从自己的类路径中查找并装载目标类。

    这一点是从安全角度考虑的,试想,如果有一个人编写了一个恶意的基础类(如java.lang.String)并装载到JVM中,将会引起多么可怕的后果,

    但是由于有了“全盘负责委托机制”,java.lang.String永远是根装载器来装载的,这样就避免了上述安全隐患的发生。

       

  • 相关阅读:
    猜数字游戏
    Visual Studio Code如何编写运行C、C++
    Git Submodule使用完整教程
    同一客户端多个git账号的配置
    让 Git Bisect 帮助你
    GitHub 风格的 Markdown 语法
    git 命令图解
    图解git中的最常用命令
    Understanding the Bias-Variance Tradeoff
    Seven Techniques for Data Dimensionality Reduction
  • 原文地址:https://www.cnblogs.com/xinde123/p/7601091.html
Copyright © 2020-2023  润新知