美文网首页
[java]22、反射

[java]22、反射

作者: 史记_d5da | 来源:发表于2021-10-24 08:13 被阅读0次

    1、概述

    框架:半成品软件。可以在框架的基础上进行软件开发,简化编码
    反射:将类的各个组成部分封装为其他对象,这就是反射机制


    反射

    将字节码文件Person.class封装成 Field对象、Constructor对象、Method对象
    好处:
    1)、可以在程序运行过程中,操作这些对象。
    2)、可以解耦,提高程序的可扩展性。
    获取Class对象的方式:
    1)、Class.forName("全类名"):将字节码文件加载进内存,返回Class对象
    多用于配置文件,将类名定义在配置文件中。读取文件,加载类
    2)、类名.class:通过类名的属性class获取
    多用于参数的传递
    3)、对象.getClass():getClass()方法在Object类中定义着。
    多用于对象的获取字节码的方式

    public class ReflectDemo1 {
        public static void main(String[] args) throws ClassNotFoundException {
            // 1、 Class.forName("全名");
            Class cls1 = Class.forName("com.sj.demo01.domain.Person");
            System.out.println(cls1);
            // 2、类名.class
            Class cls2 = Person.class;
            System.out.println(cls2);
            Person p = new Person();
            // 3、对象.getClass()
            Class cls3 = p.getClass();
            System.out.println(cls3);
            System.out.println(cls1 == cls2); // true
            System.out.println(cls1 == cls3); // true
        }
    }
    

    结论:
    同一个字节码文件(*.class)在一次程序运行过程中,只会被加载一次,不论通过哪一种方式获取的Class对象都是同一个。

    2、Class对象功能

    1、获取功能:
    1)、获取成员变量们
    Field[] getFields() :获取所有public修饰的成员变量
    Field getField(String name) 获取指定名称的 public修饰的成员变量
    Field[] getDeclaredFields() 获取所有的成员变量,不考虑修饰符
    Field getDeclaredField(String name)
    2)、获取构造方法们
    Constructor<?>[] getConstructors()
    Constructor<T> getConstructor(类<?>... parameterTypes)
    Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
    Constructor<?>[] getDeclaredConstructors()
    3)、获取成员方法们:
    Method[] getMethods()
    Method getMethod(String name, 类<?>... parameterTypes)
    Method[] getDeclaredMethods()
    Method getDeclaredMethod(String name, 类<?>... parameterTypes)
    4)、获取全类名
    String getName()

    // Person.java
    public class Person {
        private String name;
        private int age;
        public String a;
        String b;
        private String c;
        protected String d;
    
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }
        public Person() {
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
        public void eat() {
            System.out.println("eat...");
        }
        public void eat(String food) {
            System.out.println("eat..." + food);
        }
        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    

    1、Field
    Field:成员变量
    操作:
    1)、设置值
    void set(Object obj, Object value)
    2)、获取值
    get(Object obj)
    3)、忽略访问权限修饰符的安全检查
    setAccessible(true):暴力反射

    public class ReflectDemo02 {
        public static void main(String[] args) throws Exception {
            Class personClass = Person.class;
            // 1、获取成员变量
            Field[] fields = personClass.getFields();
            for (Field field : fields) {
                System.out.println(field);
            }
            System.out.println("----------");
            Field a = personClass.getField("a");
            // 获取变量a的值
            Person p = new Person();
            // 设置a的值
            a.set(p, "我的");
            Object value = a.get(p);
            System.out.println(value);
            System.out.println("----------");
            // getDeclaredFields()获取所有的成员变量
            Field[] declaredFields = personClass.getDeclaredFields();
            for (Field declaredField : declaredFields) {
                System.out.println(declaredField);
            }
            // getDeclaredField()获取某个属性
            Field d = personClass.getDeclaredField("c");
            // 忽略访问权限修饰符的安全检查
            d.setAccessible(true); // 暴力反射
            Object value2 = d.get(p);
            System.out.println(value2);
        }
    }
    

    2、Constructor:构造方法
    创建对象:
    T newInstance(Object... initargs)
    如果使用空参数构造方法创建对象,操作可以简化:Class对象的newInstance方法

    public class ReflectDemo3 {
        public static void main(String[] args) throws Exception {
            Class personClass = Person.class;
            //1、 Constructor<T> getConstructor(类<?>... parameterTypes)
            Constructor constructor = personClass.getConstructor(String.class, int.class);
            System.out.println(constructor);
            // 创建对象
            Object person = constructor.newInstance("张三", 18);
            System.out.println(person);
    
            Constructor constructor1 = personClass.getConstructor();
            System.out.println(constructor1);
            // 创建对象
            Object person1 = constructor1.newInstance();
            System.out.println(person1);
            // 此方法 is deprecated
            Object o = personClass.newInstance();
            System.out.println(o);
            // 构造私有参数时,需要设置
            //constructor1.setAccessible(true);
        }
    }
    

    3、Method:方法对象
    执行方法:
    Object invoke(Object obj, Object... args)
    获取方法名称:
    String getName:获取方法名

    public class ReflectDemo4 {
        public static void main(String[] args) throws Exception {
            Class personClass = Person.class;
            // 获取指定名称的方法
            Method eat = personClass.getMethod("eat");
            Person p = new Person();
            eat.invoke(p);
    
            Method eat1 = personClass.getMethod("eat", String.class);
            eat1.invoke(p, "饭");
            System.out.println("-----------");
            // 获取所有public方法
            Method[] methods = personClass.getMethods();
            for (Method method : methods) {
                System.out.println(method);
    //            method.setAccessible(true); // 暴力获取
                System.out.println(method.getName());
            }
            // 获取类名
            String className = personClass.getName();
            System.out.println(className);
        }
    }
    

    3、反射案例

    需求:写一个"框架",不能改变该类的任何代码的前提下,可以帮我们创建任意类的对象,并且执行其中任意方法

    // pro.properties
    className=com.sj.demo01.domain.Person
    methodName=eat
    // ReflectTest.java
    public class ReflectTest {
        public static void main(String[] args) throws Exception {
            // 加载配置文件
            Properties pro = new Properties();
            // 获取class目录下的配置文件
            ClassLoader classLoader = ReflectTest.class.getClassLoader();
            InputStream is = classLoader.getResourceAsStream("pro.properties");
            pro.load(is);
            // 获取配置文件中定义的数据
            String className = pro.getProperty("className");
            String methodName = pro.getProperty("methodName");
            // 加载该类进内存
            Class cls = Class.forName(className);
            // 创建对象
            Constructor constructor = cls.getConstructor();
            Object obj = constructor.newInstance();
            // 获取方法对象
            Method method = cls.getMethod(methodName);
            // 执行方法
            method.invoke(obj);
        }
    }
    

    相关文章

      网友评论

          本文标题:[java]22、反射

          本文链接:https://www.haomeiwen.com/subject/onllaltx.html