反射

反射

反射是框架的灵魂

反射也是动态化代理的基础

在运行期间 动态的获取类的信息以及对类进行操作的机制(获取编译后类的class字节码文件)

把每一个class文件放大来看 那么其中的每个组成部分都是一个又一个的对象

一个类由 具有相同属性和行为的对象组成

一个class文件看成一个类,每个类里边都有成员变量 方法 构造方法可以被看成属性

1.获取class对象

 public static void getClassMothods()  {
    //1.获取class对象
        //1
        Class<Car> carClass = Car.class;
        //2
        Car  car = new Car();
        final Class<? extends Car> aClass = car.getClass();
        //3
        try {
            final Class<?> aClass1 = Class.forName("com.klay.sm.reflect.Car");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }

2.获取成员变量信息

public static void getFieldsMothods(){
  //	全路径
        try {
             Class<?> aClass = Class.forName("com.klay.sm.reflect.Car");
             Object o = aClass.newInstance();
            System.out.println(o);
            //获取成员变量  getFields()只能获取public修饰的属性  包括从父类继承的属性
            final Field[] fields = aClass.getFields();
            System.out.println(fields.length);
            for (Field field:fields){
                System.out.println(field);
                System.out.println("==========");
                System.out.println(field.getName());
            }
            //getDeclaredFields()只获取本类声明的属性  public private修饰的都可以
            aClass.getDeclaredFields();
            System.out.println(fields.length);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }

3.获取方法对象 并且调用

 public static void getMethods() {
        try {
          //调用类的class文件
            Class<?> aClass = Class.forName("com.qy30.sm.reflect.Car");
//            aClass.getConstructor()
          //实例化
            Object obj = aClass.newInstance();
            // 调用public方法(包括继承的)
            Method[] methods = aClass.getMethods();
          
        /*    for (Method method : methods) {
                System.out.println(method.getName());
            }*/
            // 调用本类的方法  public和private
            Method[] declaredMethods = aClass.getDeclaredMethods();
         /*   for (Method declaredMethod : declaredMethods) {
                System.out.println(declaredMethod.getName());
            }*/
            //1,根据方法名和形参类型获取指定的方法对象
            Method declaredMethod = aClass.getDeclaredMethod("run");
            // 把方法改为可访问的public
            declaredMethod.setAccessible(true);
            // 通过反射调用方法 传对象以及实参  调用方法invoke
            declaredMethod.invoke(obj);
            // 2,拿到有参数的 方法对象
            Method addOil = aClass.getDeclaredMethod("addOil", String.class, Integer.class);
            addOil.invoke(obj, "abc", 10);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

4,练习题

public static void exercise() {
        try {
          //调用class文件
            Class<?> stuClass = Class.forName("com.qy30.sm.reflect.Student");
          //实例化
            Object student = stuClass.newInstance();
          //调用本类方法
            Method setCar = stuClass.getDeclaredMethod("setCar", Car.class);
			// 通过配置文件传入进来
            Class<?> aClass = Class.forName("配置文件(args[]或者读取配置文件)");
          //车的实例化
            Object o = aClass.newInstance();
          //invoke()调用方法  传入参数
            setCar.invoke(student, o);
            System.out.println(student);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

5,构造器的使用

 public static void getConstructor() {
        try {
            Class<?> aClass = Class.forName("com.qy30.sm.reflect.BmwCar");
            // 默认会调用无参构造  没有无参构造就不能用这种办法
//            Object o = aClass.newInstance();
            // 获取构造器  public
            Constructor<?>[] constructors = aClass.getConstructors();
            // 所有的构造器
            Constructor<?>[] declaredConstructors = aClass.getDeclaredConstructors();
          //一个构造器
            Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(Double.class);
          //更改修饰符
            declaredConstructor.setAccessible(true);
          //创建构造器对象
            Object o1 = declaredConstructor.newInstance(6.6);
            System.out.println(o1);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

6.类加载器

​ 按需加载 使用到的时候才会加载

​ 字节码文件只会被加载一次,不会重复加载

​ 静态代码块在类加载到内存的那一刻执行 并且只能加载一次

java–>complier编译为.class文件–>由类加载器加载到内存–>字节码校验文件–>解释器解释 成机器指令–>操作系统

java中的加载器

  1. 启动类加载器 bootstrap class loader

    核心类的加载器 核心类 不是java代码写的

  2. 扩展类加载器 extend class loader

    \jre\lib\ext 加载内部的类

  3. 应用类加载器 application class loader

    加载用户自定义类

  4. 其他类加载器

双亲委派机制

​ 当一个类加载器收到了类加载的请求 他不会自己去尝试加载这个类 而是把这个请求委派给父类加载器去完成 每一个层次的类加载器都是如此 因此所有的加载请求最终都应该传送到顶层的启动类加载器中,只有当父加载器反馈自己无法完成这个加载请求(他的搜索范围中没有找到所需的类)时,子加载器才会尝试自己去加载,从而保证每个类只会被加载一次

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值