美文网首页
java中的反射Reflection

java中的反射Reflection

作者: 单向时间轴 | 来源:发表于2018-09-29 14:36 被阅读35次

    目录:

    概念:

    反射(Reflection)是Java程序开发语言的特征之一,它允许运行中的Java程序获取自身的信息,并且可以操作类或对象的内部属性。主要是指程序可以访问、检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

    编译期与运行期:

    编译期:将java文件执行为class文件的过程,如通过new的方式创建对象是在编译期。方法重载,泛型均在编译期
    运行期:将class文件执行到最终结果。如通过反射创建对象,方法重写,多态。

    编译后product1=30 ; product2 = number3 * number4

    特点:

    优点:

    1,能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。(如:工厂设计模式)
    2,android的开发中,反射可以获取系统未开发的属性,或修改系统类的private属性
    3,反射在Android框架中的应用。如:https://juejin.im/post/5a2c1c5bf265da431956334c

    缺点:

    1,使用反射影响性能
    2,破坏类的结果
    3,存在安全隐患

    使用场景:

    1,修改系统的属性,获取系统的属性,如:状态栏的高度
    2,动态代理的实现
    3,Android中第三方框的使用

    使用:

    1, 获取类的对象(三种方式,基本数据类型如:boolean需要使用Boolean)

    //1,使用类名.class
    Class studentClass = Student.class;
    //2,使用Class的forName方法
    try {
    Class forName = Class.forName("com.learn.study.bean.reflect.Student");
    }catch (ClassNotFoundException e) {
    e.printStackTrace();
    }
    //3,通过对象的getClass()方法获取
    Student student =new Student();
    Class aClass = student.getClass();
    //获取父类的class对象
    Class<? super Student> superclass = studentClass.getSuperclass();
    

    2,获取构造方法与创建对象

    //1,获取当前类的所有非private的构造方法,无则返回length=0的数组
    Constructor<?>[] constructors = studentClass.getConstructors();
    //2,获取当前类指定参数的非private构造方法,无则异常:NoSuchMethodException
     Constructor<Student> constructor = studentClass.getConstructor(String.class, Integer.class);
    //3,获取当前类的所有构造方法,包含private
     Constructor<Student> declaredConstructor = studentClass.getDeclaredConstructor();
    //4,获取当前类指定参数的构造方法,包含private
     Constructor<Student> declaredConstructor1 = studentClass.getDeclaredConstructor(String.class, Integer.class);
    
    //1,使用class对象创建类的对象(注:只能针对非private的无参构造函数)
    Student student = studentClass.newInstance();
    //2,使用获取的构造方法创建对象
    Constructor<Student> declaredConstructor = studentClass.getDeclaredConstructor();
    declaredConstructor.setAccessible(true);  //针对private的构造方法
    Student student = declaredConstructor.newInstance(null);
    declaredConstructor.setAccessible(false);
    

    3,获取成员变量

     //1,获取类下的所有非private成员变量
    Field[] fields = studentClass.getFields();
    //2,获取指定名称的非private成员变量
    Field aa = studentClass.getField("aa");
     //3,获取所有的成员变量
    Field[] declaredFields = studentClass.getDeclaredFields();
    //4,获取指定的成员变量
    Field mName = studentClass.getDeclaredField("mName");
    
     //获取成员变量的值
     mName.setAccessible(true);
     String aaStr = (String) mName.get(student);
    Field mTest = studentClass.getDeclaredField("mTest");
    mTest.setAccessible(true);
     //静态的成员变量,参数可以为:null
     String test = (String) mTest.get(null);
    

    4,获取方法

    //1,获取类下所有的非private方法
    Method[] methods = studentClass.getMethods();
    //2,获取类下指定的非private方法
    Method doStudy = studentClass.getMethod("doStudy");
     //3,获取类下的所有方法,包含private
    Method[] declaredMethods = studentClass.getDeclaredMethods();
     //4,获取类下指定的方法,包含private
    Method setName = studentClass.getDeclaredMethod("setName", String.class);
    
    //调用方法并获取值
    Method getName = studentClass.getDeclaredMethod("getName");
     getName.setAccessible(true);
    String invoke = (String) getName.invoke(student);
    Method setTest = studentClass.getDeclaredMethod("setTest", String.class);
    setTest.setAccessible(true);
    //静态方法调用时可以不传入对象
    setTest.invoke(null, "mmmm");
    String test2 = (String) mTest.get(null);
    

    5,编写反射工具类时的注意点:

    方法中的int类型在反射中需要传入int.class,但传入的具体值如:10,使用getClass()后变成了java.lang.Integer,故出现异常:NoSuchFieldException,此时需要获取所有的方法,进行参数匹配。

    //反射操作带参数的方法
    public ReflectUtil method(String methodName, Object... args) {
        Class<?>[] tem = argsToClass(args);
        Method[] methods = type.getMethods();
        if (methods != null && methods.length > 0) {
            boolean hasMethod = false;
            int index = 0;
            for (int i = 0; i < methods.length; i++) {
                Method method = methods[i];
                Class<?>[] parameterTypes = method.getParameterTypes();
                if (methodName.equals(method.getName()) && parameterTypes.length == tem.length && match(parameterTypes, tem)) {
                    hasMethod = true;
                    index = i;
                    break;
                }
            }
            if (hasMethod) {
                try {
                    Method method = methods[index];
                    mValue = method.invoke(mObject, args);
                    return this;
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }
            } else {
                Method[] declaredMethods = type.getDeclaredMethods();
                if (declaredMethods != null && declaredMethods.length > 0) {
                    boolean hasMethod2 = false;
                    int index2 = 0;
                    for (int i = 0; i < declaredMethods.length; i++) {
                        Method declaredMethod = declaredMethods[i];
                        Class<?>[] parameterTypes = declaredMethod.getParameterTypes();
                        if (methodName.equals(declaredMethod.getName()) && parameterTypes.length == tem.length && match(parameterTypes, tem)) {
                            hasMethod2 = true;
                            index2 = i;
                            break;
                        }
                    }
                    if (hasMethod2) {
                        try {
                            Method declaredMethod = declaredMethods[index2];
                            declaredMethod.setAccessible(true);
                            mValue = declaredMethod.invoke(mObject, args);
                            declaredMethod.setAccessible(false);
                            return this;
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
        return this;
    }
    
    //进行方法的参数匹配
    private boolean match(Class[] parameterTypes, Class<?>[] tem) {
        for (int i = 0; i < parameterTypes.length; i++) {
            if (checkClass(parameterTypes[i]) != checkClass(tem[i])) {
                return false;
            }
        }
       return true;
    }
    
    //将基本数据类型的class转换为对应包装类的class
    private Class<?> checkClass(Class<?> type) {
        if (type == null) {
            return null;
        } else if (type == byte.class) {
            return Byte.class;
        } else if (type == short.class) {
            return Short.class;
        } else if (type == int.class) {
            return Integer.class;
        } else if (type == long.class) {
            return Long.class;
        } else if (type == boolean.class) {
            return Boolean.class;
        } else if (type == char.class) {
            return Character.class;
        } else if (type == float.class) {
            return Float.class;
        } else if (type == double.class) {
            return Double.class;
        }
        return type;
    }
    

    相关文章

      网友评论

          本文标题:java中的反射Reflection

          本文链接:https://www.haomeiwen.com/subject/heqfoftx.html