Android 插件化开发——基础底层知识(反射)

继续我们的底层知识学习,为后面的插件化开发作准备。
上一篇:
Android 插件化开发——基础底层知识(Service)

本篇博客学习反射,其实说到反射,正常开发用不到,所以之前也不太会,不,是不会。如果不是为了学习了解插件化,真的还是不会主动去学习反射。


反射


关于反射,我们需要掌握以下几点:

  • 获得一个类
  • 获得类对象
  • 获得静态函数
  • 获得非静态函数
  • 获得类非静态成员变量并修改
  • 获得类的静态成员变量并修改
  • 反射泛型

再说之前我们先定义一个类:

/**
 * author: liumengqiang
 * Date : 2019/6/20
 * Description :
 */
public class TestModel {

    private String name = "hello";

    private static String name_1 = "我是静态字段";

    public TestModel() {
        System.out.println("创建构造函数");
//        Log.e("无参数构造", ".....");
    }

    public TestModel(int a) {
        System.out.println("创建构造函数" + a);
//        Log.e("无参数构造", ".....");
    }

    public TestModel(int a, String arg) {
        System.out.println("创建构造函数" + a + " " + arg);
    }

    private void getMethod1() {
        System.out.print("我是私有实例方法!");
    }

    private static void getStaticMethod2() {
        System.out.println("我是私有静态方法");
    }

    private String getName() {
        return name;
    }

    private String getName_1() {
        return name_1;
    }


}

获得一个类
反射获得一个类,用的最多的是:forName

Class<?> aClass = Class.forName("com.liumengqiang.afrbtccoin.main.TestModel");

其中com.liumengqiang.afrbtccoin.main 是包名, TestModel是类。

获得类对象
获取类的无参构造函数,使用getDeclaredConstructor方法:

Class<?> aClass = Class.forName("com.liumengqiang.afrbtccoin.main.TestModel");
Constructor<?> constructor = aClass.getDeclaredConstructor();
Object newInstance = constructor.newInstance();

获取有参数构造方法:

Class<?> aClass = Class.forName("com.liumengqiang.afrbtccoin.main.TestModel");
Class[] arg2 = {int.class, String.class};
Constructor<?> constructor2 = aClass.getDeclaredConstructor(arg2);
Object newInstance2 = constructor2.newInstance(2, "hello");

对应TestModel两个参数的构造方法。

获得静态函数

//获TestModel类
Class<?> classObject = getClassObject();
//由于是静态类,所以不用活得类对象,直接调用getDeclaredMethod方法。
 Method method2 = classObject.getDeclaredMethod("getStaticMethod2");
 method2.setAccessible(true);
 //该静态方法没有参数
method2.invoke(null);

步骤:

  1. 先获得TestModel类
  2. 直接调用getDeclaredMethod方法
  3. 通过方法invoke,由于没有参数,所以传递null。

注意:getStaticMethod2是要反射的方法名

获得非静态函数

			//获取类对象
            Class<?> classObject = Class.forName("com.liumengqiang.afrbtccoin.main.TestModel");
            Constructor<?> constructor = classObject.getDeclaredConstructor();
            Object o = constructor.newInstance();

            //获取到这个私有方法
            Method privateMethod = classObject.getDeclaredMethod("getMethod1");
            privateMethod.setAccessible(true);
            //调用这个私有方法
            Object result = privateMethod.invoke(o);

步骤:

  1. 获取TestModel类
  2. 获得类实例
  3. 通过getDeclaredMethod方法反射获得Method
  4. 调用方法

获得类非静态成员变量并修改

			//获取类对象
            Class<?> classObject = Class.forName("com.liumengqiang.afrbtccoin.main.TestModel");
            Constructor<?> constructor = classObject.getDeclaredConstructor();
            Object o = constructor.newInstance();
            //获取私有字段
            Field field = classObject.getDeclaredField("name");
            field.setAccessible(true);
            Object fieldObj = field.get(o);
            System.out.println(fieldObj);
            field.set(o, "hello world!");//设置私有字段值

步骤:

  1. 获取类对象
  2. 创建类实例
  3. 通过getDeclaredField获得字段
  4. 获得字段信息
  5. 设置字段信息

获得类的静态成员变量并修改

		Class<?> classObject = Class.forName("com.liumengqiang.afrbtccoin.main.TestModel");
            Field name_1 = classObject.getDeclaredField("name_1");
            System.out.println(name_1.get("name_1"));
            name_1.setAccessible(true);
            name_1.set(null, "我是被修改过的值");

步骤和获得静态函数步骤一样。

关于反射泛型,在此先不讲述,先消化反射的基本技术,关于泛型,后面Hook startActivity的时候在讲述。


反射工具类



/**
 * author: liumengqiang
 * Date : 2019/6/20
 * Description : 反射工具类
 */
public class ReflexUtil {
    /**
     * 获取类对象
     * @param className
     * @return
     */
    public static Object createObject(String className) {
        return createObject(className, new Class[]{}, new Object[]{});
    }

    /**
     * 获取类对象(1个参数)
     * @param className
     * @param paramType 参数类型
     * @param paramValue 参数值
     * @return
     */
    public static Object createObject(String className, Class paramType, Object paramValue) {
        Class[] paramsType = new Class[]{paramType};
        Object[] paramsValue = new Object[]{paramValue};
        return createObject(className, paramsType, paramsValue);
    }

    /**
     * 获取类对象(2个参数)
     * @param className
     * @param paramsType 参数类型
     * @param paramsValue 参数值
     * @return
     */
    public static Object createObject(String className, Class[] paramsType, Object[] paramsValue) {
        try {
            Class<?> aClass = Class.forName(className);
            Constructor<?> constructor = aClass.getDeclaredConstructor(paramsType);
            constructor.setAccessible(true);
            return constructor.newInstance(paramsValue);
        } catch(ClassNotFoundException e) {
            Log.e("createObject: ", "ClassNotFoundException");
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            Log.e("createObject: ", "NoSuchMethodException");
            e.printStackTrace();
        } catch (InstantiationException e) {
            Log.e("createObject: ", "InstantiationException");
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            Log.e("createObject: ", "IllegalAccessException");
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            Log.e("createObject: ", "InvocationTargetException");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取静态方法
     * @param className
     * @param methodName
     * @return
     */
    public static Object invokeStaticMethod(String className, String methodName) {
        return invokeStaticMethod(className, methodName, new Class[]{}, new Object[]{});
    }

    /**
     *获取静态方法(1个参数)
     * @param className
     * @param methodName
     * @param paramType
     * @param paramValue
     * @return
     */
    public static Object invokeStaticMethod(String className, String methodName, Class paramType, Object paramValue) {
        return invokeStaticMethod(className, methodName, new Class[]{paramType}, new Object[]{paramValue});
    }

    /**
     * 获取静态方法(2个参数)
     * @param className
     * @param methodName 方法名
     * @param paramsType 方法参数类型
     * @param paramsValue 方法参数值
     * @return
     */
    public static Object invokeStaticMethod(String className, String methodName, Class[] paramsType, Object[] paramsValue ) {
        try {

            // 第一步:获取 IActivityManagerSingleton
            Class<?> aClass = Class.forName(className);
            Method method = aClass.getDeclaredMethod(methodName);
            method.setAccessible(true);
            return method.invoke(null);
        } catch (ClassNotFoundException e) {
            Log.e("----:", "" + e);
            e.printStackTrace();
        }  catch (IllegalAccessException e) {
            Log.e("----:", "" + e);
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取非静态实例方法
     * @param objectInstance
     * @param methodName
     * @return
     */
    public static Object invokeInstanceMethod(Object objectInstance, String methodName) {
        return invokeInstanceMethod(objectInstance, methodName, new Class[]{}, new Object[]{});
    }

    /**
     * 获取非静态实例方法(1个参数)
     * @param objectInstance
     * @param methodName
     * @param paramType
     * @param paramValue
     * @return
     */
    public static Object invokeInstanceMethod(Object objectInstance, String methodName, Class paramType, Object paramValue) {
        return invokeInstanceMethod(objectInstance, methodName, new Class[]{paramType}, new Object[]{paramValue});
    }

    /**
     * 获取非静态实例方法(2个方法)
     * @param objectInstance
     * @param methodName
     * @param paramsType
     * @param paramsValue
     * @return
     */
    public static Object invokeInstanceMethod(Object objectInstance, String methodName, Class[] paramsType, Object[] paramsValue) {
        try {
            Method method = objectInstance.getClass().getDeclaredMethod(methodName, paramsType);
            method.setAccessible(true);
            return method.invoke(objectInstance, paramsValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取非静态字段
     * @param className
     * @param fieldName
     * @return
     */
    public static Object getFieldValue(String className, Object objInstance, String fieldName) {
        try {
            Class<?> aClass = Class.forName(className);
            Field field = aClass.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(objInstance);
        } catch (NoSuchFieldException e) {
            Log.e("getFieldValue:", "NoSuchFieldException");
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            Log.e("getFieldValue:", "IllegalAccessException");
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            Log.e("getFieldValue:", "ClassNotFoundException");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 设置非静态字段
     * @param className
     * @param fieldName
     * @param fieldValue
     */
    public static void setFieldValue(String className, Object objInstance, String fieldName, Object fieldValue) {
        try {
            Class<?> aClass = Class.forName(className);
            Field field = aClass.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(objInstance, fieldValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取静态字段
     * @param className
     * @param fieldName
     * @return
     */
    public static Object getStaticFieldValue(String className, String fieldName) {
        try {
            Class<?> aClass = Class.forName(className);
            Field declaredField = aClass.getDeclaredField(fieldName);
            declaredField.setAccessible(true);
            return declaredField.get(fieldName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 设置静态字段
     * @param className
     * @param fieldName
     * @param fieldValue
     */
    public static void setStaticFieldValue(String className, String fieldName, Object fieldValue ) {
        try {
            Class<?> aClass = Class.forName(className);
            Field field = aClass.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(null, fieldValue);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

注意:之后我们的插件化文章中的反射,用到的都是这个工具类。
注意:之后我们的插件化文章中的反射,用到的都是这个工具类。
注意:之后我们的插件化文章中的反射,用到的都是这个工具类。

拓展:getMethods 和 getDeclaredMethods区别:
getMethods: 用于获取public的成员方法,包括从父类继承的public方法;
getDeclaredMethods: 用于获取当前类中的方法(不分public和非public),不包括从父类继承的方法。
getField: 用于获取public的成员变量,包括从父类继承的public成员变量;
getDeclaredField: 用于获取当前类中的变量(不分public和非public),不包括从父类继承的变量。

下一篇文章讲述代理模式。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值