zoukankan      html  css  js  c++  java
  • java 反射 的详细总结

    1.前言

      什么是反射?

    引用教科书的解释:

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

      如何通俗理解?

    其实说白了,就是将任意一个类对象【原对象】注入一个反射类里,可以对原对象解析,
    获取里面的所有属性和方法信息,并可以调用;使用原对象获取对象类型后获取无参构造函数再实例一个无参对象,
    那么这个对象就是该原对象的反射对象,反射对象有着与原对象一样的属性和方法,可以动态获取任意对象信息和动态的调用任意对象方法,
    如果不做其他增强操作,就相当于反射对象复制了原对象。
    由此可见,可以调用原方法的同时做一些其他操作,也就是增强操作,这也就是动态代理的底层原理。

    2.操作

    使用代码理解【里面有很多注释,足够理解了啊】

    (1)文件目录结构

     (2)建一个实体类

    package com.example.javabaisc.reflect.deme;
    
    import java.util.HashMap;
    import java.util.UUID;
    
    /**
     * 实体类
     */
    public class Info {
        //被保护的属性
        private int id;
        private String name;
        //无参构造函数
        public Info(){};
        //有参构造函数
        public Info(int id ,String name){
            this.id = id ;
            this.name = name;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        //共有自定义方法
        public String dosomething(String str){
            System.out.println("我是自定义方法,输入参数是="+str);
            return str+"==="+ UUID.randomUUID().toString();
        }
    
        //私有被保护的自定义方法
        private String love(int num){
            System.out.println("我是自定义方法,输入参数是="+num);
            return num+"==="+ UUID.randomUUID().toString();
        }
        //公共使用属性
        public String publicParam;
    
    
    }
    View Code

    有各种属性和方法

    (3)反射类

    package com.example.javabaisc.reflect.deme;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    
    /**
     * 反射类
     */
    public class DoReflect {
    
        Logger logger = LoggerFactory.getLogger(getClass());
    
        /*
        反射方法【类似于复制操作】
         */
        public Object copy(Object object) throws Exception {
            /**
             * 获取传入原对象的类型
             */
            // 写法1:【泛型可写可不写】
            Class<?> classType = object.getClass();
            logger.warn("获取传入原对象的类型:" + classType.getName());
            //写法2:
            //原对象的文件路径【注意,没有文件java后缀,不建议这样使用,否则需要传入路对象文件路径】
    //        String infoURL = "com.example.javabaisc.reflect.deme.Info";
    //        Class<? > classType = Class.forName(infoURL);
            //
            //写法3:
            //原对象的文件路径【不建议这样使用,否则需要传入路对象文件路径】
    //        String infoURL =  "com.example.javabaisc.reflect.deme.Info";
    //        Class<?> classType = DoReflect.class.getClassLoader().loadClass(infoURL);
            //
            //看看,方法2和3 是不是很眼熟,就是以前使用原生的jdbc连接数据库放入操作啊,原来jdbc底层是使用了映射。。。
            //但是还是方法1简单,而且容易理解
            //
            //
            /**
             *  根据原对象类型,获取无参构造函数后实例一个新的对象,这个就是映射对象
             */
            //如果newInstance没有参数,则可以不写空的超类数组
            Object objectCopy = classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
    //        //上面一句话可以分步写:
    //        //步骤1:获取无参构造函数对象
    //        Constructor<?> constructor = classType.getConstructor(new Class[]{});
    //        logger.warn("无参构造函数对象名字:" + constructor.getName());
    //        //步骤2:获反射对象
    //        Object objectCopy = constructor.newInstance(new Object[]{});
            logger.warn("反射对象名字:" + objectCopy.toString());
            //
            /**
             * 获取所有方法
             */
            Method[] methods = classType.getDeclaredMethods();
            logger.warn("===================================================================");
            for (Method method : methods) {
                /*
                获取方法修饰符
                 */
                String modifier = Modifier.toString(method.getModifiers());
                logger.warn("获取方法修饰符:" + modifier);
                /*
                获取返回参数类型
                 */
    //            [会获取完整的类型路径名,如 java.lang.String]
                String returnType = method.getReturnType().getName();
                logger.warn("获取返回参数类型,写法1:" + returnType);
    //            [仅会获取名字,如String]
                String returnType2 = method.getReturnType().getSimpleName();
                logger.warn("获取返回参数类型,写法2:" + returnType2);
                /*
                获取方法名字
                 */
                String methodName = method.getName();
                logger.warn("获取方法名字:" + methodName);
                //获取所有传入参数类型
                Class<?>[] params = method.getParameterTypes();
                logger.warn("------------------------------------------------------------");
                for (Class<?> param : params) {
                    /*
                    获取参数类型名字
                     */
                    //写法1和2都是获取完整的类型路径名,如 java.lang.String
                    String paramTypeName = param.getName();
                    String paramTypeName2 = param.getTypeName();
                    //该写法3仅会获取类型名字,如String
                    String paramTypeName3 = param.getSimpleName();
                    logger.warn("获取参数类型名字,写法1:" + paramTypeName);
                    logger.warn("获取参数类型名字,写法2:" + paramTypeName2);
                    logger.warn("获取参数类型名字,写法3:" + paramTypeName3);
                }
                logger.warn("------------------------------------------------------------");
            }
            logger.warn("===================================================================");
    
            /**
             * 获取指定的方法
             */
            logger.warn("使用getMethod获取指定的方法,但是仅能获取public修饰的方法");
            //参数分别是 方法名字 、参数类型
            Method method = classType.getMethod("dosomething", new Class[]{String.class});
            // 指定方法的修饰符
            String modifier = Modifier.toString(method.getModifiers());
            logger.warn("指定方法的修饰符:" + modifier);
            String returnTypeName = method.getReturnType().getSimpleName();
            logger.warn("指定方法的返回类型:" + returnTypeName);
            //指定方法的名子
            String methodName = method.getName();
            logger.warn("指定方法的名子:" + methodName);
            Class<?>[] params = method.getParameterTypes();
            for (Class<?> param : params) {
                logger.warn("指定方法的参数类型:" + param.getSimpleName());
            }
            logger.warn("===================================================================");
            logger.warn("使用privateMethod获取指定的方法,可以获取被保护的方法");
            //参数分别是 方法名字 、参数类型
            Method privateMethod = classType.getDeclaredMethod("love", new Class[]{int.class});
            // 指定方法的修饰符
            String modifier2 = Modifier.toString(privateMethod.getModifiers());
            logger.warn("指定方法的修饰符:" + modifier2);
            String returnTypeName2 = privateMethod.getReturnType().getSimpleName();
            logger.warn("指定方法的返回类型:" + returnTypeName2);
            //指定方法的名子
            String methodName2 = privateMethod.getName();
            logger.warn("指定方法的名子:" + methodName2);
            Class<?>[] params2 = privateMethod.getParameterTypes();
            for (Class<?> param : params2) {
                logger.warn("指定方法的参数类型:" + param.getSimpleName());
            }
    
            logger.warn("===================================================================");
            /**
             * 获取所有属性
             */
            logger.warn("获取所有属性");
            Field[] fields = classType.getDeclaredFields();
            logger.warn("------------------------------------------------------------");
            for (Field field : fields) {
                //属性修饰符
                String modifer = Modifier.toString(field.getModifiers());
                logger.warn("属性修饰符:" + modifer);
                //属性类型
                String fieldType = field.getType().getSimpleName();
                logger.warn("属性类型:" + fieldType);
                //属性名字
                String fieldName = field.getName();
                logger.warn("字段名字:" + fieldName);
            }
            logger.warn("------------------------------------------------------------");
            logger.warn("===================================================================");
            /**
             * 获取指定属性
             */
            logger.warn("使用getField获取指定属性,但是仅能获取public修饰的属性");
            Field field = classType.getField("publicParam");
            //属性修饰符
            String modifer = Modifier.toString(field.getModifiers());
            logger.warn("属性修饰符:" + modifer);
            //属性类型
            String fieldType = field.getType().getSimpleName();
            logger.warn("属性类型:" + fieldType);
            //属性名字
            String fieldName = field.getName();
            logger.warn("字段名字:" + fieldName);
            logger.warn("------------------------------------------------------------");
            logger.warn("使用getDeclaredField获取指定属性,可以获取被保护的属性");
            Field field2 = classType.getDeclaredField("id");
            //属性修饰符
            String modifer2 = Modifier.toString(field2.getModifiers());
            logger.warn("属性修饰符:" + modifer2);
            //属性类型
            String fieldType2 = field2.getType().getSimpleName();
            logger.warn("属性类型:" + fieldType2);
            //属性名字
            String fieldName2 = field2.getName();
            logger.warn("字段名字:" + fieldName2);
            logger.warn("===================================================================");
            /**
             * 调用对象的方法,
             * 首先需要获取方法对象,然后通过参数来选择是调用原对象的方法还是反射对象的方法
             */
            logger.warn("调用对象的方法");
            /*
            向原对象 setname 传入name值,然后 getname 获取原对象name值,然后将获取的值使用反射对象的 setname 方传入后,使用反射对象的 getname 获取
             */
            //拼接 setname 方法名字
            String setMethodName = "set" + ("name".substring(0, 1).toUpperCase()) + ("name".substring(1));
            //拼接 getname 方法名字
            String getMethodName = "get" + ("name".substring(0, 1).toUpperCase()) + ("name".substring(1));
            //获取 setname 方法对象
            Method setMethod = classType.getDeclaredMethod(setMethodName, new Class[]{String.class});
            //获取 getname 方法对象
            Method getMethod = classType.getDeclaredMethod(getMethodName, new Class[]{});
            //调用原对象的 setname方法,并赋值
            String mname = "你大爷啊啊啊";
            setMethod.invoke(object, new Object[]{mname});
            //调用原对象的 getname方法 获取name值
            Object value = getMethod.invoke(object, new Object[]{});
            logger.warn("调用 原对象 的 getname方法 获取name值为:" + value);
            //调用反射对象的 setname方法,并赋值
            setMethod.invoke(objectCopy, new Object[]{value});
            //调用反射对象的 getname方法 获取name值
            Object reflectValue = getMethod.invoke(objectCopy, new Object[]{});
            logger.warn("调用 反射对象 的 getname方法 获取name值为:" + reflectValue);
            logger.warn("===================================================================");
    
    
            //返回反射对象
            return objectCopy;
    
        }
    
    
    }
    View Code

    (4)测试类

    package com.example.javabaisc.reflect.deme;
    
    import org.junit.jupiter.api.Test;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    /**
     * 测试类
     */
    public class RETest {
        Logger log = LoggerFactory.getLogger(getClass());
    
        @Test
        public void t() throws Exception {
    
            //实例实体类
            Info info = new Info();
            //实例反射类
            DoReflect doReflect = new DoReflect();
            //调用反射类的反射方法,将实体类对象注入进去 ,返回这个实体类的反射对象
            Info infoReflect = (Info) doReflect.copy(info);
            //调用反射对象的方法
            String res = infoReflect.dosomething("扫地啦");
            log.warn("调用反射对象的方法的结果是:{}",res);
            //调用反射对象的getname方法[已经在反射方法了做了赋值操作]
            String name = infoReflect.getName();
            log.warn("调用反射对象的getname方法的结果是:{}",name);
    
        }
    
    
    }
    View Code

    3.测试

    运行测试类,控制台打印

    16:16:40.811 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取传入原对象的类型:com.example.javabaisc.reflect.deme.Info
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 反射对象名字:com.example.javabaisc.reflect.deme.Info@78a2da20
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ===================================================================
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取方法修饰符:public
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取返回参数类型,写法1:java.lang.String
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取返回参数类型,写法2:String
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取方法名字:getName
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取方法修饰符:public
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取返回参数类型,写法1:int
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取返回参数类型,写法2:int
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取方法名字:getId
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取方法修饰符:public
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取返回参数类型,写法1:void
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取返回参数类型,写法2:void
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取方法名字:setName
    16:16:40.814 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取参数类型名字,写法1:java.lang.String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取参数类型名字,写法2:java.lang.String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取参数类型名字,写法3:String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取方法修饰符:public
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取返回参数类型,写法1:java.lang.String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取返回参数类型,写法2:String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取方法名字:dosomething
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取参数类型名字,写法1:java.lang.String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取参数类型名字,写法2:java.lang.String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取参数类型名字,写法3:String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取方法修饰符:private
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取返回参数类型,写法1:java.lang.String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取返回参数类型,写法2:String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取方法名字:love
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取参数类型名字,写法1:int
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取参数类型名字,写法2:int
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取参数类型名字,写法3:int
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取方法修饰符:public
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取返回参数类型,写法1:void
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取返回参数类型,写法2:void
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取方法名字:setId
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取参数类型名字,写法1:int
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取参数类型名字,写法2:int
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取参数类型名字,写法3:int
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ===================================================================
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 使用getMethod获取指定的方法,但是仅能获取public修饰的方法
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 指定方法的修饰符:public
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 指定方法的返回类型:String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 指定方法的名子:dosomething
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 指定方法的参数类型:String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ===================================================================
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 使用privateMethod获取指定的方法,可以获取被保护的方法
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 指定方法的修饰符:private
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 指定方法的返回类型:String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 指定方法的名子:love
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 指定方法的参数类型:int
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ===================================================================
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 获取所有属性
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 属性修饰符:private
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 属性类型:int
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 字段名字:id
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 属性修饰符:private
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 属性类型:String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 字段名字:name
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 属性修饰符:public
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 属性类型:String
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 字段名字:publicParam
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ===================================================================
    16:16:40.815 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 使用getField获取指定属性,但是仅能获取public修饰的属性
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 属性修饰符:public
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 属性类型:String
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 字段名字:publicParam
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ------------------------------------------------------------
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 使用getDeclaredField获取指定属性,可以获取被保护的属性
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 属性修饰符:private
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 属性类型:int
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 字段名字:id
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ===================================================================
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 调用对象的方法
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 调用 原对象 的 getname方法 获取name值为:你大爷啊啊啊
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - 调用 反射对象 的 getname方法 获取name值为:你大爷啊啊啊
    16:16:40.816 [main] WARN com.example.javabaisc.reflect.deme.DoReflect - ===================================================================
    我是自定义方法,输入参数是=扫地啦
    16:16:41.085 [main] WARN com.example.javabaisc.reflect.deme.RETest - 调用反射对象的方法的结果是:扫地啦===fd1cfc80-e653-4661-9f06-77780f363a5d
    16:16:41.087 [main] WARN com.example.javabaisc.reflect.deme.RETest - 调用反射对象的getname方法的结果是:你大爷啊啊啊
    View Code
  • 相关阅读:
    GDB Practice
    GCC常用命令
    使用VS2010 C#编写ActiveX控件
    [.NET] 使用 .NET Framework 開發 ActiveX Control
    VC2005开发MFC ActiveX控件
    Register DLL and OCX
    COM组件开发实践
    Java Invoke C and C++ Using JNI
    Unable to cast object of type 'System.Int32' to type 'System.String'.
    SharePoint wiki 分类获取所有的
  • 原文地址:https://www.cnblogs.com/c2g5201314/p/13172767.html
Copyright © 2011-2022 走看看