zoukankan      html  css  js  c++  java
  • 反射

    反射

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

    用途: 在日常的第三方应用开发过程中,经常会遇到某个类的某个成员变量、方法或是属性是私有的或是只对系统应用开放,这时候就可以利用Java的反射机制通过反射来获取所需的私有成员或是方法。当然,也不是所有的都适合反射,之前就遇到一个案例,通过反射得到的结果与预期不符。阅读源码发现,经过层层调用后在最终返回结果的地方对应用的权限进行了校验,对于没有权限的应用返回值是没有意义的缺省值,否则返回实际值起到保护用户的隐私目的。

    注意: 有关反射的类都在java.lang.reflect包下

    实例前提

    例如我们有一个类:

    后面代码都是根据下面的Reflect类进行

    package cn.test.reflection; // 包
    
    public class Reflect {
        // 成员属性
        public String name; // 公有
        private int age; // 私有
        
        // 普通方法
        public void show() { // 公有
            System.out.println("show()...");
        }
        private void show2(String name, int age) { // 私有
            System.out.println("show2()...");
            System.out.println(name);
            System.out.println(age);  
        }
        
        // getter,setter,toString,有参无参构造等....
    

    获取Class对象的三种方式

    • Class<?> clazz1 = Reflect.class; (高效,推荐使用)
    • Class<?> clazz2 = Class.forName("cn.tedu.reflection.Reflect");
    • Class<?> clazz3 = new Reflect().getClass();

    打印clazz1, clazz2, clazz3输出:

    class cn.test.reflection.Reflect
    class cn.test.reflection.Reflect
    class cn.test.reflection.Reflect
    

    反射构造方法

    方法:

    返回值 方法 说明
    Constructor[] getConstructors(); 返回所有public修饰的构造方法
    Constructor getConstructor(Class<?>... parameterTypes) 返回无参构造方法
    参数是构造参数的类型,例如
    clazz.getConstructor(String.class, int.class);

    代码:

    Class<?> clazz = Reflect.class;
    // 获取所有构造方法
    Constructor<?>[] constructors = clazz.getConstructors();
    // 遍历构造方法
    for (Constructor<?> constructor : constructors) {
        // 输出参数数组
        System.out.println("参数: " + Arrays.toString(constructor.getParameterTypes()));
    }
    

    结果:

    参数: [int]
    参数: [class java.lang.String, int]
    

    反射成员变量

    方法:

    返回值 方法 说明
    Field[] getFields(); 返回所有public修饰的属性
    Field getField(String name); 返回指定的public属性,
    name是属性名
    例如:
    clazz.getField("age")

    代码:

    Class<?> clazz = Reflect.class;
    Field[] fields = clazz.getFields();// 获取所有属性
    for (Field field : fields) { // 遍历属性
        // 输出属性名和类型
        System.out.println(field.getName() + " : " + field.getType());
    }
    

    结果: (只能获取public的属性)

    name : class java.lang.String
    

    反射成员方法

    返回值 方法 参数
    Method[] getMethods() 返回所有public修饰的方法
    Method getMethod(String name, Class<?>... parameterTypes) 返回指定的方法,
    name是方法名,
    后面的参数是方法的参数类型.例如clazz.getMethod("show2", String.class, int.class);

    代码:

    Class<?> clazz = Reflect.class;
    Method[] methods = clazz.getMethods();
    for (Method method : methods) {
        System.out.println("方法名: " + method.getName());
        System.out.println("参数: " + Arrays.toString(method.getParameterTypes()));
        System.out.println("返回值: " + method.getReturnType());
        System.out.println("-------------------------------------");
    }
    

    结果:

    方法名: toString
    参数: []
    返回值: class java.lang.String
    -------------------------------------
    方法名: getName
    参数: []
    返回值: class java.lang.String
    -------------------------------------
    方法名: setName
    参数: [class java.lang.String]
    返回值: void
    -------------------------------------
    ...
    // 等等...(包括Object)的方法
    

    反射创建对象

    返回值 方法 说明
    T (泛型) newInstance() 创建对象(调用无参构造)

    使用Class创建对象

    代码:

    Class<?> clazz = Reflect.class;
    // 创建对象
    Reflect r1 = (Reflect) clazz.newInstance();
    
    // 使用对象的方法
    r1.setAge(1);
    r1.setName("张三");
    System.out.println(r1);
    

    结果:

    Reflect{name='张三', age=1}
    

    使用指定构造器创建

    代码:

    Class<?> clazz = Reflect.class;
    // 获取指定构造器
    Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
    // 创建对象
    Reflect r2 = (Reflect) constructor.newInstance("李四", 44);
    System.out.println(r2);
    

    结果:

    Reflect{name='李四', age=44}
    

    反射private属性

    反射private的属性可用于反射普通属性

    私有属性必须设置setAccessible(true);, 设置为true才能进行访问private的

    方法:

    返回值 方法 说明
    Field getDeclaredField(String name) 返回指定的属性, name是属性名
    Field[] getDeclaredFields() 返回所有属性

    代码:

    // 获取Class对象
    Class<?> clazz = Reflect.class;
    // 暴力反射
    Field age = clazz.getDeclaredField("age");
    // 获取类型
    System.out.println(age.getType().getName()); // int
    // 设置私有可见, 否则还是无法访问私有的属性值
    age.setAccessible(true);
    // 设置私有变量值
    Object obj = clazz.newInstance();
    age.set(obj, 2);
    // 获取私有变量的值
    System.out.println(age.get(obj));
    

    结果:

    int
    2
    

    反射private方法

    反射private的方法可用于反射普通方法

    私有属性必须设置setAccessible(true);, 设置为true才能进行访问private的

    方法:

    返回值 方法 说明
    Method getDeclaredMethod(String name, Class<?>... parameterTypes) 获取指定的方法, name是方法名
    例如:clazz.getDeclaredMethod("show2", String.class, int.class);
    Method[] getDeclaredMethods() 获取所有的方法

    代码:

    // 获取Class独享
    Class<?> clazz = Reflect.class;
    // 暴力反射
    // 第一个参数是方法名,
    // 第二个参数是这个方法需要啥类型的参数
    Method show2 = clazz.getDeclaredMethod("show2", String.class, int.class);
    
    // 设置访问权限, --私有可见.  否则无法访问private修饰的方法
    show2.setAccessible(true);
    
    // 让方法执行起来
    // 第一个参数是, 要执行那个对象的方法
    // 第二个参数, 要给方法传入什么实参
    Object obj = clazz.newInstance();
    show2.invoke(obj, "jack", 20);
    

    结果:

    show2()...jack : 20
    jack
    20
    
  • 相关阅读:
    【python】Python 资源大全中文版
    获取最新chromedriver.exe的方法,并查阅最新的chromedriver.exe支持到什么chrome版本
    appium 重新启动apk
    git 命令操作
    [转]IDEA 出现编译错误 Multi-catches are not supported a this language level 解决方法
    jmeter压测前清理内存
    清理kafka zookeeper
    windows 自动移动maven jar包到jmeter 文件夹下面
    jmeter 压测duobbo接口,施压客户端自己把自己压死了
    kafak manager + zookeeper + kafka 消费队列快速清除
  • 原文地址:https://www.cnblogs.com/zpKang/p/12970397.html
Copyright © 2011-2022 走看看