美文网首页
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;
}

相关文章

  • Reflection反射 和 Mirror镜像

    /* Reflection反射 和 Mirror镜像 Java 中的Reflection反射 是一种在运行时...

  • Java基础之反射

    Java基础之—反射(非常重要)Java中反射机制详解Java进阶之reflection(反射机制)——反射概念与...

  • Java反射机制入门

    Java反射机制入门 一、什么是反射 JAVA反射机制(The JAVA reflection mechanism...

  • Java反射

    1. 什么是反射(Reflection )? Java 语言的反射(Reflection)机制,就是通过动态的方式...

  • 详解Java反射机制(Reflection)

    详解Java反射机制(Reflection) 反射机制的作用 JAVA反射机制是在运行状态中,对于任意一个类,都能...

  • 深入理解 Java 反射和动态代理

    简介 什么是反射 反射(Reflection)是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序...

  • 深入理解 Java 反射和动态代理

    简介 什么是反射 反射(Reflection)是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序...

  • 深入理解 Java 反射和动态代理

    简介 什么是反射 反射(Reflection)是 Java 程序开发语言的特征之一,它允许运行中的 Java 程序...

  • Java之 反射机制

    引子 什么是反射 反射 (Reflection) 是 Java 的特征之一,它允许运行中的 Java 程序获取自身...

  • Java 反射机制

    [1]. java反射详解[2]. Java Reflection(反射机制)详解[3]. 深入理解Java类型...

网友评论

      本文标题:java中的反射Reflection

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