zoukankan      html  css  js  c++  java
  • Java反射理解

    什么是Java反射机制

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

    反射提供的功能:

    • 运行时判断任意一个对象的类
    • 运行时构造任意一个类的对象
    • 运行时判定一个类具有的成员变量和方法
    • 运行时调用任意一个对象的方法
    • 动态代理

    反射机制类:

    • java.lang.Class: 类
    • java.lang.reflect.Constructor : 构造方法
    • java.lang.reflect.Field : 类的成员变量
    • java.lang.reflect.Method : 类的方法
    • java.lang.reflect.Modifier : 访问权限

    实现反射:

    1. 获取Class对象:3种方式

    Dog dog = new Dog("tom");
    //1.通过对象获取
    Class class1 = dog.getClass();
    //2.通过类的属性获取
    class1 = Dog.class;
    //3.通过Class类的静态方法获取
    try {
        class1 = Class.forName("Dog");
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
    }
    

    2. 获取class对象的摘要信息:

    //判断是否是基础类
    class1.isPrimitive();
    //java.lang.Boolean
    //java.lang.Character
    //java.lang.Byte
    //java.lang.Short
    //java.lang.Integer
    //java.lang.Long
    //java.lang.Float
    //java.lang.Double
    //java.lang.Void
    //判断是否是集合
    class1.isArray();
    //判断是否是注解
    class1.isAnnotation();
    //判断是否是接口
    class1.isInterface();
    //判断是否是枚举
    class1.isEnum();
    //判断是否是匿名内部类
    class1.isAnonymousClass();
    //判断是否被某个注解类修饰
    class1.isAnnotationPresent(Deprecated.class);
    //获取内部类
    Class<?>[] innerClasses = class1.getDeclaredClasses();
    //获取外部类
    Class<?> outClasses = class1.getDeclaringClass();
    

    3. 获取class对象的属性,方法,构造函数等

    class Base {
        public String age;
        public Base() {}
    }
    
    class Dog extends Base {
        private String name;
        protected String shortName;
        public Dog(String name) {this.name = name;}
        private Dog() {}
        public void displayName() {System.out.println(name);}
    }
    
    //所有public属性,包括从父类继承的
    Field[] publicFields = class1.getFields();
    //所有属性,只包括自身声明过得
    Field[] allFields = class1.getDeclaredFields();
    //所有公共方法,包括从父类继承的
    Method[] publicMethods = class1.getMethods();
    //所有方法,只包括自身声明过得
    Method[] allMethods = class1.getDeclaredMethods();
    //所有公共构造函数
    Constructor[] publicConstructors = class1.getConstructors();
    //所有构造函数,,只包括自身声明过得
    Constructor[] allConstructors = class1.getDeclaredConstructors();
    
    输出:
    ---publicFields---
    public java.lang.String Base.age
    ---allFields---
    private java.lang.String Dog.name
    protected java.lang.String Dog.shortName
    ---publicMethods---
    public void Dog.displayName()
    public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
    public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
    public final void java.lang.Object.wait() throws java.lang.InterruptedException
    public boolean java.lang.Object.equals(java.lang.Object)
    public java.lang.String java.lang.Object.toString()
    public native int java.lang.Object.hashCode()
    public final native java.lang.Class java.lang.Object.getClass()
    public final native void java.lang.Object.notify()
    public final native void java.lang.Object.notifyAll()
    ---allMethods---
    public void Dog.displayName()
    ---publicConstructors---
    public Dog(java.lang.String)
    ---allConstructors---
    public Dog(java.lang.String)
    private Dog()
    

    4. class对象动态生成

    try {
    	//1. 调用Dog类的无参构造函数(这种方式需要确保无参构造函数不是私有的)
        obj = class1.newInstance();
        Constructor cs = class1.getDeclaredConstructor(new Class[]{String.class});
        //2. 调用有参构造函数
        obj = cs.newInstance(new Object[]{"tom's dog"});
    } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
        e.printStackTrace();
    }
    

    5. 动态调用函数

    //获取方法对应的Method对象
    Method method = class1.getDeclaredMethod("displayName");
    //调用函数
    method.invoke(obj);
    //获取含参方法
    Method method2 = class1.getDeclaredMethod("setName", new Class[]{String.class});
    //调用函数并传递参数
    method2.invoke(obj, new Object[]{"new name"});
    

    6. 通过反射机制获取泛型类型

    摘自:Java学习之反射机制及应用场景

    //People类
    public class People<T> {}
    //Person类继承People类
    public class Person<T> extends People<String> implements PersonInterface<Integer> {}
    //PersonInterface接口
    public interface PersonInterface<T> {}
    

    获取泛型类型

    Person<String> person = new Person<>();
    //第一种方式 通过对象getClass方法
    Class<?> class1 = person.getClass();
    Type genericSuperclass = class1.getGenericSuperclass();//获取class对象的直接超类的 Type
    Type[] interfaceTypes = class1.getGenericInterfaces();//获取class对象的所有接口的Type集合
    
    getComponentType(genericSuperclass);
    getComponentType(interfaceTypes[0]);
    

    getComponetType:

    private Class<?> getComponentType(Type type) {
    Class<?> componentType = null;
    if (type instanceof ParameterizedType) {
        //getActualTypeArguments()返回表示此类型实际类型参数的 Type 对象的数组。
        Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments();
        if (actualTypeArguments != null && actualTypeArguments.length > 0) {
        componentType = (Class<?>) actualTypeArguments[0];
        }
    } else if (type instanceof GenericArrayType) {
        // 表示一种元素类型是参数化类型或者类型变量的数组类型
        componentType = (Class<?>) ((GenericArrayType) type).getGenericComponentType();
    } else {
        componentType = (Class<?>) type;
    }
    return componentType;
    }
    

    7. 通过反射获取注解:

            Class<Mela> melaClass = null;
            try {
                melaClass = (Class<Mela>) Class.forName("Mela");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            try {
                //获取指定方法
                Method method = melaClass.getDeclaredMethod("setName", String.class);
                //获取所有注解
                Annotation[] annotations = method.getAnnotations();
                //获取类型指定注解
                Annotation annotationType1 = method.getAnnotation(Deprecated.class);
                //获取所有参数注解
                Annotation[][] paramsAno = method.getParameterAnnotations();
                for (Annotation[] aParamsAno : paramsAno) {
                    for (Annotation anAParamsAno : aParamsAno) {
                        System.out.println(anAParamsAno);
                    }
                }
                System.out.println(annotationType1);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
    
            //获取所有成员变量的注解
            Field[] fields = melaClass.getDeclaredFields();
            for (Field f : fields) {
                Annotation[] annotations = f.getDeclaredAnnotations();
                for (Annotation a : annotations) {
                    System.out.println(a);
                }
            }
        }
    

    8. 反射机制的应用场景:

    • 逆向代码 ,例如反编译
    • 与注解相结合的框架 例如Retrofit
    • 单纯的反射机制应用框架 例如EventBus 2.x
    • 动态生成类框架 例如Gson
  • 相关阅读:
    网络传输协议 UDP & TCP 详解
    OSI 七层协议
    (01day)python接口测试
    Python2和Python3的区别,以及为什么选Python3的原因
    JAVA反编译工具
    JAR反编译工具
    webdriver19-witchto方法
    webdriver实例14-Xpath定位的几种方法
    webdirver实例1--查找元素
    Qt插件开发
  • 原文地址:https://www.cnblogs.com/jiy-for-you/p/7282051.html
Copyright © 2011-2022 走看看