• java反射


    简介

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

    原理

    深入理解Java虚拟机》一文中介绍,类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载、连接、初始化、使用、卸载。而JVM在加载阶段要完成的3件事情中正好有Class对象的生成:

    1. 通过一个类的全限定名来获取定义此类的二进制字节流。
    2. 将这个字节流所代表的的静态存储结构转化为方法区的运行时数据结构。
    3. 在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据的访问入口。

    获取一个类的Class对象的三种方法,对应的通过Class对象创建类实例也有三种方法:

    // 通过包名+类名
    Class<TestClass> class = Class.forName("com.zkw.TestClass");
    
    // 通过类名
    Clas<TestClass> class = TestClass.class;
    
    // 通过对象
    TestClass tc = new TestClass();
    Class<TestClass> class = tc.getClass();
     
    // 通过Class对象创建类实例
    TestClass testClass = class.newInstance();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    使用

    在正式开始前,先介绍一个最重要的方法setAccessible(),使用反射可以获取一个类的所有方法及属性,但是某些方法和属性是私有的,这时候就需要通过该方法将方法和类设置为public;

    注: setAccessible()方法并不是修改类的访问权限,而是是否禁止Java 语言访问检查(值为true则禁止)
    在这里插入图片描述

    相关类

    类名用途
    Class类代表类的实体,在运行的Java应用程序中表示类和接口
    Field类代表类的成员变量(成员变量也称为类的属性)
    Method类代表类的方法
    Constructor类代表类的构造方法

    class类

    ● 获得类相关的方法
    方法用途
    Cast把对象转换成代表类或是接口的对象
    getClassLoader()获得类的加载器
    getClasses()返回一个数组,数组中包含该类中所有公共类和接口类的对象
    getDeclaredClasses()返回一个数组,数组中包含该类中所有类和接口类的对象
    forName(String className)根据类名返回类的对象
    getName()获得类的完整路径名字
    newInstance()创建类的实例(不推荐使用,而是使用Constructor的newInstance()方法)
    getPackage()获得类的包
    getSimpleName()获得类的名字
    getSuperclass()获得当前类继承的父类的名字
    getInterfaces()获得当前类实现的类或是接口
    ● 获得类中属性相关的方法
    方法用途
    getField(String name)获得某个公有的属性对象
    getFields()获得所有公有的属性对象
    getDeclaredField(String name)获得某个属性对象
    getDeclaredFields()获得所有属性对象
    ● 获得类中注解相关的方法
    方法用途
    getAnnotation(Class annotationClass)返回该类中与参数类型匹配的公有注解对象
    getAnnotations()返回该类所有的公有注解对象
    getDeclaredAnnotation(Class annotationClass)返回该类中与参数类型匹配的所有注解对象
    getDeclaredAnnotations()返回该类所有的注解对象
    ● 获得类中构造器相关的方法
    方法用途
    getConstructor(Class… parameterTypes )获得该类中与参数类型匹配的公有构造方法
    getConstructors()获得该类的所有公有构造方法
    getDeclaredConstructor(Class… parameterTypes)获得该类中与参数类型匹配的构造方法
    getDeclaredConstructors()获得该类所有构造方法
    ● 获得类中方法相关的方法
    方法用途
    getMethod(String name, Class… parameterTypes)获得该类某个公有的方法
    getMethods()获得该类所有公有的方法
    getDeclaredMethod(String name, Class… parameterTypes)获得该类某个方法
    getDeclaredMethods()获得该类所有方法

    Field类

    方法用途
    equals(Object obj)属性与obj相等则返回true
    get(Object obj)获得obj中对应的属性值
    set(Object obj, Object value)设置obj中对应属性值
    getModifiers()获取该属性的修饰符(static、final等)

    Method类

    方法用途
    invoke(Object obj, Object… args)传递object对象及参数调用该对象对应的方法

    Constructor类

    方法用途
    newInstance(Object… initargs)根据传递的参数创建类的对象

    实战

    在日常开发中反射用的最多的地方可能是将map转换为实体bean:

    publicclass MapUtilByReflect {
    
        /**
         * 对象转Map
         * @param object
         * @return
         * @throws IllegalAccessException
         */
        public static Map beanToMap(Object object) throws IllegalAccessException {
            Map<String, Object> map = new HashMap<String, Object>();
            // 获取所有属性
            Field[] fields = object.getClass().getDeclaredFields();
            for (Field field : fields) {
                // 禁止Java 语言访问检查
                field.setAccessible(true);
                map.put(field.getName(), field.get(object));
            }
            return map;
        }
    
        /**
         * map转对象
         * @param map
         * @param beanClass
         * @param 
         * @return
         * @throws Exception
         */
        publicstatic <T> T mapToBean(Map map, Class<T> beanClass) throws Exception {
            T object = beanClass.newInstance();
            Field[] fields = object.getClass().getDeclaredFields();
            for (Field field : fields) {
                int mod = field.getModifiers();
    
                // 一定不要忘记加上该判断
                if (Modifier.isStatic(mod) || Modifier.isFinal(mod)) {
                    continue;
                }
                
                field.setAccessible(true);
                if (map.containsKey(field.getName())) {
                	 // 赋值
                    field.set(object, map.get(field.getName()));
                }
            }
            return 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
  • 相关阅读:
    丨EGFR FISH 探针解决方案
    静态代理和动态代理笔记
    计算机图形学中的曲线问题——贝塞尔曲线的绘制
    【开源电路】ST-LINK/V2、ST-LINK/V2-1、DAP-LINK烧录器(已验证)
    世界杯优化算法及其Python实现
    婚恋相亲交友红娘小程序源码开发搭建方法
    Unknown custom element: <el-image>无法使用该组件,升级element-ui版本后项目报错
    草料二维码生成器怎么连接打通其他应用?
    linux如何抓包数据
    记一次 .NET 某医院预约平台 非托管泄露分析
  • 原文地址:https://blog.csdn.net/Wyunpeng/article/details/126824577