• JavaSE之反射


    Class类

    Class类创建的对象我们称为Class对象/类对象/字节码对象

    Class对象会保存类中的信息(构造方法, 成员方法, 成员变量等)
    有了Class对象就能得到类中的所有信息。

    反射的概念

    在程序的运行过程中, 通过Class对象得到类中的信息(构造方法, 成员方法, 成员变量), 并操作他们

    这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制。非正常的手段操作对象。

    反射的好处

    使用反射创建对象,代码更复杂,无视修饰符,
    功能更强大灵活

    反射的应用场景

    IDEA的智能提示
    框架Spring/SpringMVC/Mybatis

    三种获取Class对象的方式

    类名.class

    对象.getClass()

    Class.forName(“类全名”);

    注意:三种方式获取到的是同一个Class对象

    public static void main(String[] args) throws ClassNotFoundException {
            // 类名.class    Class:
            Class<Employee> cls1 = Employee.class;
            System.out.println(cls1);
            // 对象.getClass()    Class:
            Employee employee = new Employee();
            Class<? extends Employee> cls2 = employee.getClass();
            System.out.println(cls2);
            // Class.forName("类全名"); 包名.类名  第三种使用最灵活(常用),因为类不存在也能通过编译
            Class<?> cls3 = Class.forName("com.itheima.bean.Employee");
            System.out.println(cls3);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    Class类中的方法

    String getSimpleName(); 获得类名字符串:类名

    String getName(); 获得类全名:包名.类名

    public static void main(String[] args) {
            // 1.得到Class对象
            Class<Employee> cls = Employee.class;
            // 2.得到类中的信息
            String name = cls.getName();
            System.out.println(name);
            String simpleName = cls.getSimpleName();
            System.out.println(simpleName);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    Class中获取构造器的方法

    getConstructors()

    getConstructor (Class… parameterTypes)

    getDeclaredConstructors()

    getDeclaredConstructor (Class… parameterTypes)

    反射得到的构造器可以做什么?

    创建对象

    public newInstance(Object… initargs)

    如果是非public的构造器,需要打开权限(暴力反射),然后再创建对象
    setAccessible(boolean)

    反射可以破坏封装性,私有的也可以执行了。

    public class Demo06 {
        // 得到所有public的构造器: getConstructors
        @Test
        public void test01() {
            // 1.得到Class对象
            Class<Employee> cls = Employee.class;
            // 2.得到所有public的构造器
            Constructor<?>[] constructors = cls.getConstructors();
            for (Constructor o:constructors){
                System.out.println(o);
            }
        }
    
        // 得到一个public的构造器: getConstructor
        @Test
        public void test02() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
            // 1.得到Class对象
            Class<Employee> cls = Employee.class;
            // 2.得到一个public的构造器
            Constructor<Employee> constructor = cls.getConstructor();
            System.out.println(constructor);
            Constructor<Employee> constructor1 = cls.getConstructor(String.class, int.class);
            System.out.println(constructor1);
            // Constructor c = cls.getConstructor(); // 匹配无参 public Employee()
    
            // 3.使用构造器创建对象
            Employee employee = constructor.newInstance();
            Employee employee1 = constructor1.newInstance("张三", 88);
            System.out.println(employee);
            System.out.println(employee1);
    
        }
    
        // 得到所有存在的构造器: getDeclaredConstructors
        @Test
        public void test03() {
            // 1.得到Class对象
            Class<Employee> cls = Employee.class;
            // 2.得到所有存在的构造器     Declared:声明的,存在的
            //包括私有,protected等
            Constructor<?>[] constructors = cls.getDeclaredConstructors();
            for (Constructor o : constructors){
                System.out.println(o);
            }
        }
    
        // 得到一个存在的构造器: getDeclaredConstructor
        @Test
        public void test04() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
            // 1.得到Class对象
            Class<Employee> cls = Employee.class;
            // 2.得到一个存在的构造器
            Constructor<Employee> constructor = cls.getDeclaredConstructor();
            Constructor<Employee> constructor1 = cls.getDeclaredConstructor(String.class);
            // 3.使用构造器创建对象
            Employee employee = constructor.newInstance();
            constructor1.setAccessible(true);
            Employee employee1 = constructor1.newInstance("王五");
            System.out.println(employee);
            System.out.println(employee1);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    获取成员方法对象

    Class中获取成员方法的方法

    getMethods()

    getMethod(String name, Class… parameterTypes)

    getDeclaredMethods()

    getDeclaredMethod (String name, Class… parameterTypes)

    反射得到成员方法可以做什么?

    依然是在某个对象中触发该方法执行。

    Object invoke​(Object obj, Object… args)

    如果某成员方法是非public的,需要打开权限(暴力反射),然后再触发执行
    setAccessible(boolean)

    public class Demo07 {
        // 得到所有public的方法: getMethods
        @Test
        public void test01() {
            // 1.得到Class对象
            Class<Employee> cls = Employee.class;
            // 2.得到所有public的方法
            Method[] methods = cls.getMethods();
            for (Method m : methods) {
                System.out.println(m);
            }
        }
    
        @Test
        // 得到所有存在的方法: getDeclaredMethods
    
        public void test02() {
            // 1.得到Class对象
            Class<Employee> cls = Employee.class;
            // 2.得到所有存在的方法
            Method[] methods = cls.getDeclaredMethods();
            for (Method m : methods) {
                System.out.println(m);
            }
        }
    
        // 得到一个public的方法: getMethod
        @Test
        public void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException {
            // 1.得到Class对象
            Class<Employee> cls = Employee.class;
            // 2.得到一个public的方法
            Method setName = cls.getMethod("setName", String.class);
            // 3.调用方法
            // Object invoke(Object obj, Object... args)
            Employee instance = cls.getConstructor().newInstance();
            instance.setAge(19);
            setName.invoke(instance, "李四");
    
            Method getName = cls.getMethod("getName");
            Object invoke = getName.invoke(instance);
            System.out.println(invoke);
            // Object obj: 调用方法的对象
            // Object... args: 方法的参数
            // Object: 返回值
    
        }
    
        // 得到一个存在的方法: getDeclaredMethod
        @Test
        public void test04() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
            // 1.得到Class对象
            Class<?> cls = Class.forName("com.itheima.bean.Employee");
            // 2.得到一个存在的方法
            Method sleep = cls.getDeclaredMethod("sleep", int.class);
            // 3.调用方法
            Object instance = cls.getConstructor().newInstance();
            sleep.setAccessible(true);
            Object hours = sleep.invoke(instance, 2);
            System.out.println(hours);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62

    获取成员变量

    获取类中成员变量对象的方法

    getFields()

    getField(String name)

    getDeclaredFields()

    getDeclaredField(String name)

    反射得到成员变量可以做什么?(不常用,因为我们一般通过方法来取值赋值,这样直接拿成员变量赋值效率低)

    依然是在某个对象中取值和赋值。

    void set​(Object obj, Object value):

    Object get​(Object obj)

    如果某成员变量是非public的,需要打开权限(暴力反射),然后再取值、赋值
    setAccessible(boolean)

    public class Demo08 {
        // 得到所有public的成员变量: getFields
        @Test
        public void test01() {
            // 1.得到Class对象
            Class<Employee> cls = Employee.class;
            // 2.得到所有public的成员变量
            Field[] fields = cls.getFields();
            for (Field f : fields) {
                System.out.println(f);
            }
        }
    
        // 得到所有存在的成员变量: getDeclaredFields
        @Test
        public void test02() {
            // 1.得到Class对象
            Class<Employee> cls = Employee.class;
    
            // 2.得到所有存在的成员变量
            Field[] declaredFields = cls.getDeclaredFields();
            for (Field f : declaredFields) {
                System.out.println(f);
            }
        }
    
        // 得到一个public的成员变量: getField
        @Test
        public void test03() throws NoSuchFieldException {
            // 1.得到Class对象
            Class<Employee> employeeClass = Employee.class;
            // 2.得到Field
            Field weight = employeeClass.getField("weight");
            System.out.println(weight);
        }
    
        // 得到一个存在的成员变量: getDeclaredField
        @Test
        public void test04() throws NoSuchFieldException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
            // 1.得到Class对象
            Class<Employee> employeeClass = Employee.class;
            // 2.得到Field
            Field age = employeeClass.getDeclaredField("age");
            // 3.给成员变量赋值
            // set(Object obj, Object value);
            Employee employee = employeeClass.getConstructor().newInstance();
            age.setAccessible(true);
            age.set(employee, 99);
            // Object obj: 成员变量所在对象
            // Object value: 新的值
    
            // 4.获取成员变量的值
    
            Object o = age.get(employee);
            System.out.println(o);
            // Object get(Object obj);
            // Object obj: 成员变量所在对象
            // Object: 返回成员变量的值
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60

    反射案例

    需求: 利用反射根据文件中的不同类名和方法名,创建不同的对象并调用方法。
    分析:

    通过Properties加载配置文件

    得到类名和方法名

    通过类名反射得到Class对象

    通过Class对象创建一个对象

    通过Class对象得到方法

    调用方法

    public class Demo09 {
        public static void main(String[] args) throws Exception {
            Properties properties = new Properties();
            properties.load(new FileReader("D:\\it_workspace\\src\\config.properties"));
            String className = properties.getProperty("className");
            String methodName = properties.getProperty("methodName");
            Class<?> cls = Class.forName(className);
            Object instance = cls.getConstructor().newInstance();
            Method method = cls.getMethod(methodName);
            method.invoke(instance);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在这里插入图片描述

    Teacher
    在这里插入图片描述

    最后

    如果你对本文有疑问,你可以在文章下方对我留言,敬请指正,对于每个留言我都会认真查看。

  • 相关阅读:
    Excel导入和导出
    day06 51单片机-点阵led
    如何维护知乎口碑?小马识途解析知乎口碑优化的技巧
    【游戏分享】Stellaris.Galaxy.Edition.v3.5.3-GOG all dlc
    Java学数据结构(4)——PriorityQueue(优先队列)& 二叉堆(binary heap)
    【Python刷题篇】——Python入门 012 正则表达式
    Vue——组件化开发
    《python 可视化之 matplotlib》第一章 折线图 plot
    现代卷积网络实战系列3:PyTorch从零构建AlexNet训练MNIST数据集
    Python Asyncio 之网络编程方法详解
  • 原文地址:https://blog.csdn.net/weixin_47543906/article/details/127899366