Android 反射机制

01、反射

主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。

02、反射作用

  • 反编译:将 class 文件反编译成 Java 文件。
  • 访问对象:访问 Java 对象中的属性、方法、构造方法等。

03、需要使用的类

  • java.lang.Class - 类,某个具体的类或接口
  • java.lang.reflect.Constructor - 反射构造方法
  • java.lang.reflect.Field - 反射属性
  • java.lang.reflect.Method - 反射方法
  • java.lang.reflect.Modifier - 访问修饰符的信息

04、获取 Class 对象的三种方法

  • Class.forName 方式,会让ClassLoader装载类,并进行类的初始化
  • .class 方式,ClassLoader 装载入内存,不对类进行类的初始化操作
  • 3、getClass 方式,返回类对象运行时真正所指的对象,所属类型的Class对象

区别主要在于是否进行初始化和是否在实例中获取

        // 1、Class.forName 方式,会让ClassLoader装载类,并进行类的初始化
        try {
            Class c1 = Class.forName("com.zpan.reflecttest.ReflectTest");
            Log.e("zpan", "c1 == " + c1);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        // 2、.class 方式,ClassLoader 装载入内存,不对类进行类的初始化操作
        Class c2 = ReflectTest.class;
        Log.e("zpan", "c2 == " + c2);

        // 3、getClass 方式,返回类对象运行时真正所指的对象,所属类型的Class对象
        Class c3 = new ReflectTest().getClass();
        Log.e("zpan", "c3 == " + c3);

Log

    c1 == class com.zpan.reflecttest.ReflectTest
    c2 == class com.zpan.reflecttest.ReflectTest
    c3 == class com.zpan.reflecttest.ReflectTest

05、获取构造函数(四个方法)

反射类构造函数

    public ReflectTest() { }

    public ReflectTest(String str) { }

    private ReflectTest(String str1, String str2) { }

获取构造函数

  • getConstructor(Class[] params) 根据构造函数的参数,返回一个具体的具有public属性的构造函数
  • getConstructors() 返回所有具有public属性的构造函数数组
  • getDeclaredConstructor(Class[] params) 根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
  • getDeclaredConstructors() 返回该类中所有的构造函数数组(不分public和非public属性)
        Class c2 = ReflectTest.class;

        // 1、getConstructor(Class[] params) 根据构造函数的参数,返回一个具体的具有public属性的构造函数
        try {
            Constructor constructor1 = c2.getConstructor(String.class);
            Log.e("zpan", "constructor1 ==" + constructor1);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        // 2、getConstructors()  返回所有具有public属性的构造函数数组
        Constructor[] constructors1 = c2.getConstructors();
        for (int i = 0; i < constructors1.length; i++) {
            Log.e("zpan", "constructors1 =" + i + "=" + constructors1[i]);
        }

        // 3、getDeclaredConstructor(Class[] params)  根据构造函数的参数,返回一个具体的构造函数(不分public和非public属性)
        try {
            Constructor constructor2 = c2.getDeclaredConstructor(String.class, String.class);
            Log.e("zpan", "constructor2 ==" + constructor2);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        // 4、getDeclaredConstructors() 返回该类中所有的构造函数数组(不分public和非public属性)
        Constructor[] constructors2 = c2.getDeclaredConstructors();
        for (int i = 0; i < constructors2.length; i++) {
            Log.e("zpan", "constructors2 =" + i + "=" + constructors2[i]);
        }

Log

    constructor1 ==public com.zpan.reflecttest.ReflectTest(java.lang.String)

    constructors1 =0=public com.zpan.reflecttest.ReflectTest()
    constructors1 =1=public com.zpan.reflecttest.ReflectTest(java.lang.String)

    constructor2 ==private com.zpan.reflecttest.ReflectTest(java.lang.String,java.lang.String)

    constructors2 =0=public com.zpan.reflecttest.ReflectTest()
    constructors2 =1=public com.zpan.reflecttest.ReflectTest(java.lang.String)
    constructors2 =2=private com.zpan.reflecttest.ReflectTest(java.lang.String,java.lang.String)

06、获取反射对象

注:

  • newInstance() 方法返回的是一个泛型T,我们要强转成相应的反射类。
  • 反射创建对象,可以使用Class.newInstance() 和 Constructor.newInstance() 两种方式,而前者必须要求反射类中存在一个无参的构造方法,并且有访问权限;后者适应各种类型的构造方法,无论是否有参数都可以调用,这是需要 setAccessible() 控制访问验证即可。一般建议是使用后者。
        // 无参构造创建对象
        try {
            ReflectTest r2 = (ReflectTest) c2.newInstance();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
        // 有参构造创建对象
        try {
            ReflectTest reflectTest = (ReflectTest) constructor1.newInstance("zpan");
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

07、获取反射类的方法(四个方法)

反射类方法

    public void testPublicVoidMethod() { }

    public String testPublicStringMethod() {
        return "";
    }

    private void testPrivateVoidMethod() { }
  • getMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的具有public属性的方法
  • getMethods() 返回所有具有public属性的方法数组
  • getDeclaredMethod(String name, Class[] params) 根据方法名和参数,返回一个具体的方法(不分public和非public属性)
  • getDeclaredMethods() 返回该类中的所有的方法数组(不分public和非public属性)
       Class c2 = ReflectTest.class;

        // 1、根据方法名和参数,返回一个具体的具有public属性的方法
        try {
            Method method1 = c2.getMethod("testPublicVoidMethod", null);
            Log.e("zpan", "method1 ==" + method1);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        // 2、返回所有具有public属性的方法数组
        Method[] methods1 = c2.getMethods();
        for (int i = 0; i < methods1.length; i++) {
            Log.e("zpan", "methods1 =" + i + "=" + methods1[i]);
        }

        // 3、根据方法名和参数,返回一个具体的方法(不分public和非public属性)
        try {
            Method method2 = c2.getDeclaredMethod("testPrivateVoidMethod", null);
            Log.e("zpan", "method2 ==" + method2);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        // 4、返回该类中的所有的方法数组(不分public和非public属性)
        Method[] methods2 = c2.getDeclaredMethods();
        for (int i = 0; i < methods2.length; i++) {
            Log.e("zpan", "methods2 =" + i + "=" + methods2[i]);
        }

Log

    method1 ==public void com.zpan.reflecttest.ReflectTest.testPublicVoidMethod()

    methods1 =6=public java.lang.String com.zpan.reflecttest.ReflectTest.testPublicStringMethod()
    methods1 =7=public void com.zpan.reflecttest.ReflectTest.testPublicVoidMethod()

    method2 ==private void com.zpan.reflecttest.ReflectTest.testPrivateVoidMethod()

    methods2 =1=private void com.zpan.reflecttest.ReflectTest.testPrivateVoidMethod()
    methods2 =2=public java.lang.String com.zpan.reflecttest.ReflectTest.testPublicStringMethod()
    methods2 =3=public void com.zpan.reflecttest.ReflectTest.testPublicVoidMethod()

从日志中可以看出methods1 下标出现6、7,而methods2 下标是1、2、3

  • getMethods():用于获取类的所有的public修饰域的成员方法,包括从父类继承的public方法和实现接口的public方法;
  • getDeclaredMethods():用于获取在当前类中定义的所有的成员方法和实现的接口方法,不包括从父类继承的方法。

08、获取反射类的属性(四个方法)

反射类属性

    public String mPublicStr;
    public int mPublicInt;

    private String mPrivateStr;
    protected String mProtectedStr;
  • getField(String name) 根据变量名,返回一个具体的具有public属性的成员变量
  • getFields() 返回具有public属性的成员变量的数组
  • getDeclaredField(String name) 根据变量名,返回一个成员变量(不分public和非public属性)
  • getDelcaredField() 返回所有成员变量组成的数组(不分public和非public属性)
        Class c2 = ReflectTest.class;

        // 1、getField(String name)    根据变量名,返回一个具体的具有public属性的成员变量
        try {
            Field field1 = c2.getField("mPublicStr");
            Log.e("zpan", "field1 ==" + field1);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        // 2、getFields()    返回具有public属性的成员变量的数组
        Field[] fields1 = c2.getFields();
        for (int i = 0; i < fields1.length; i++) {
            Log.e("zpan", "fields1 =" + i + "=" + fields1[i]);
        }

        // 3、getDeclaredField(String name)    根据变量名,返回一个成员变量(不分public和非public属性)
        try {
            Field field2 = c2.getDeclaredField("mProtectedStr");
            Log.e("zpan", "field2 ==" + field2);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }

        // 4、getDelcaredField()    返回所有成员变量组成的数组(不分public和非public属性)
        Field[] fields2 = c2.getDeclaredFields();
        for (int i = 0; i < fields2.length; i++) {
            Log.e("zpan", "fields2 =" + i + "=" + fields2[i]);
        }

Log

    field1 ==public java.lang.String com.zpan.reflecttest.ReflectTest.mPublicStr

    fields1 =0=public java.lang.String com.zpan.reflecttest.ReflectTest.mProtectedStr
    fields1 =1=public int com.zpan.reflecttest.ReflectTest.mPublicInt
    fields1 =2=public java.lang.String com.zpan.reflecttest.ReflectTest.mPublicStr

    field2 ==public java.lang.String com.zpan.reflecttest.ReflectTest.mProtectedStr

    fields2 =0=private java.lang.String com.zpan.reflecttest.ReflectTest.mPrivateStr
    fields2 =1=public java.lang.String com.zpan.reflecttest.ReflectTest.mProtectedStr
    fields2 =2=public int com.zpan.reflecttest.ReflectTest.mPublicInt
    fields2 =3=public java.lang.String com.zpan.reflecttest.ReflectTest.mPublicStr

09、获取类、属性、方法的修饰符

通过 int getModifiers() 方法获得修饰符,方法返回是是一个 int 型数值,每个修饰符都对应一个int型。

10、反射框架

JOOR

参考文章

Java反射机制的原理及在Android下的简单应用
Android 反射机制的理解
Android中反射的简单应用

你可能感兴趣的:(Android 反射机制)