反射解读学习

反射的概念

反射允许对成员变量 成员方法 构造方法的信息进行编程访问
在这里插入图片描述

获取对应方法的 相关的成员变量 构造方法 和 成员方法(比如idea中的方法字段名提示就是这样实现的)

在JAVA中并不是对原始的JAVA文件进行反射获取而是对对应的字节码文件
即所谓的Class文件

所以第一步是获取对应的Class文件对象

反射的作用大致就是这两类,对信息进去获取 以及获取后的使用

获取Class对象

获取Class对象一共有三种方式 分别对应代码运行的三种

  1. 在源代码阶段 Class.forname(“全类名”)
  2. 在加载阶段. 类名.class()
  3. 在运行阶段. 对象.getClass();
public class reflect_day01 {
    public static void main(String[] args) throws ClassNotFoundException {
        // 第一种方式
        // 最为常用
        Class<?> cla = Class.forName("reflectDemo.Student");
        System.out.println(cla);

        // 第二种方式
        // 常用来作为一种参数传递
        Class<Student> claz = Student.class;
        System.out.println(claz);

        // 第三种方式
        // 有类 对象的时候使用  使用情况特殊
        Student s = new Student();
        Class<? extends Student> clas = s.getClass();

        System.out.println(claz == cla);
        System.out.println(cla == clas);
    }
}

结果都是字节文件 最后都是true

获取部分详细

在这里插入图片描述

获取构造方法

在这里插入图片描述

public class reflect_day02 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException {
        // 获取class字节文件
        Class clazz = Class.forName("reflectDemo.Student");

        // 获取第一种不被保护的全部构造方法
        Constructor [] constructors = clazz.getConstructors();
        for(Constructor cons: constructors){
            System.out.println(cons);
        }
        System.out.println("***********");

        // 获取所有的包括被保护的全部构造方法
        Constructor [] constructors1 = clazz.getDeclaredConstructors();
        for(Constructor cons: constructors1){
            System.out.println(cons);
        }
        System.out.println("*************");

        // 获取某个特定的构造方法 根据传入参数确定
        Constructor constructor2 = clazz.getConstructor();
        System.out.println(constructor2);
        System.out.println("****************");

        // 获取某个有参数的构造方法
        Constructor constructor3 = clazz.getConstructor(String.class);
        System.out.println(constructor3);
        System.out.println("*************");

        // 获取某个被保护的构造方法 就必须要使用getDeclaredConstructor
        Constructor constructor4 = clazz.getDeclaredConstructor(int.class);
        System.out.println(constructor4);
        System.out.println("****************");
    }
}

以上是获取构造方法的方式
接下来是获取后如何的运用

// 获取方法修饰符
        int modifier = constructor4.getModifiers();
        System.out.println(modifier);
        // 获取参数 个数 种类 全部
        int paramCount = constructor4.getParameterCount();
        System.out.println(paramCount);
        Class[] paramTypes = constructor4.getParameterTypes();
        for(Class cla : paramTypes){
            System.out.println(cla);
        }
        Parameter[] parameters = constructor4.getParameters();
        for(Parameter param : parameters){
            System.out.println(param);
        }
        // 创建对象
        constructor4.setAccessible(true);
        Student stu = (Student)constructor4.newInstance("Tom",22);
        System.out.println(stu);

获取成员变量

在这里插入图片描述

public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
        Class clazz = Class.forName("reflectDemo.Student");

        // 获取 所有未被保护的的成员变量
        Field [] fields = clazz.getFields();
        for(Field fie : fields){
            System.out.println(fie);
        }
        System.out.println("***********");

        // 获取所有所有的成员变量
        Field [] fields1 = clazz.getDeclaredFields();
        for(Field fie : fields1){
            System.out.println(fie);
        }
        System.out.println("***********");

        // 获取单个 指定的字段
        Field field2 = clazz.getDeclaredField("age");
        System.out.println(field2);
        System.out.println("**********");

        // 获取指定字段的修饰符
        int modifier = field2.getModifiers();
        System.out.println(modifier);

        // 获取指定字段的数据类型
        Class<?> type = field2.getType();
        System.out.println(type);

        // 获取对象的该指定成员变量 且修改
        Student stu = new Student("张三",23,"男");
        field2.setAccessible(true);
        int age = (int) field2.get(stu);
        System.out.println(age);

        field2.set(stu, 24);
        System.out.println(stu);
    }

获取成员方法

在这里插入图片描述
在这里插入图片描述

 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // 第一步获取字节变量
        Class clazz = Class.forName("reflectDemo.Student");

        // 获取全部的 成员方法 会获取包括父类的公共方法
        Method [] methods = clazz.getMethods();
        for(Method method : methods){
            System.out.println(method);
        }
        System.out.println("**********");

        // 获取所有的成员方法 但不包括父类
        Method [] methods1 = clazz.getDeclaredMethods();
        for(Method method : methods1){
            System.out.println(method);
        }
        System.out.println("*************");

        // 获取某个特定的成员方法
        Method m = clazz.getDeclaredMethod("eat", String.class);
        System.out.println(m);
        System.out.println("**************");

        // 可以获取特定方法的诸多 属性
        String name = m.getName();
        System.out.println(name);
        Parameter [] parameters = m.getParameters();
        for(Parameter parameter : parameters){
            System.out.println(parameter);
        }

        // 将获取的方法执行起来
        Student s = new Student();
        m.setAccessible(true);
        Object re = m.invoke(s, "汉堡包");
        System.out.println(re.getClass());
        System.out.println(re);
    }

三种查找有许多的相似 注意多总结归纳

反射的作用

在这里插入图片描述
在这里插入图片描述

同等处理不同的类(保存不同类创建的对象值)

public class reflect_day05 {
    public static void main(String[] args) throws IOException, IllegalAccessException {
        /*
        对于任意一个对象,都可以把对象所有的字段名和值,保存到文件中去
        */
        Student s = new Student("小A",23,'女',167.5,"睡觉");
        Teacher t = new Teacher("播妞",10000);
        save(s);
    }

    //把对象里面所有的成员变量名和值保存到本地文件中
    public static void save(Object obj) throws IOException, IllegalAccessException {
        /*
        java 默认以当前项目的文件作为 当前文件
        ../在父目录查找
        ./在当前文件查找
        */
        //1.获取字节码文件的对象
        Class clazz = obj.getClass();
        //2. 创建IO流
        BufferedWriter bw = new BufferedWriter(new FileWriter("/Users/qishimuh/JavaProject/JDBC/JavaEE/src/reflectDemo/myreflect5/a.txt"));
        // 获取所有的对象 field
        Field [] fields = clazz.getDeclaredFields();

        for(Field field : fields){
            field.setAccessible(true);

            // 字段获取对应的名字 和 值
            String name = field.getName();
            Object value = field.get(obj);

            bw.write(name + " = " + value);
            bw.newLine();
        }

        bw.close();
    }
}

练习 :反射可以跟配置文件结合的方式,动态的创建对象,并调用方法

public class reflect_day06 {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        /*
        反射可以跟配置文件结合的方式,动态的创建对象,并调用方法
    */

        // 读取配置文件
        Properties properties = new Properties();
        FileInputStream fis = new FileInputStream("./prop.properties");
        properties.load(fis);
        fis.close();
        System.out.println(properties);

        // 获取全类名
        String classname = (String)properties.get("classname");
        String methodName = (String)properties.get("method");

        // 利用反射创建对象 并执行
        Class clazz = Class.forName(classname);
        Constructor [] constructors = clazz.getDeclaredConstructors();
//        for(Constructor constructor: constructors){
//            System.out.println(constructor);
//        }
        Constructor constructor = clazz.getConstructor();
        Object stu = constructor.newInstance();
        System.out.println(stu);

        Method met = clazz.getDeclaredMethod(methodName);
        met.invoke(stu);
    }
}

总结

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值