继续我们的底层知识学习,为后面的插件化开发作准备。
上一篇:
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);
步骤:
- 先获得TestModel类
- 直接调用getDeclaredMethod方法
- 通过方法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);
步骤:
- 获取TestModel类
- 获得类实例
- 通过getDeclaredMethod方法反射获得Method
- 调用方法
获得类非静态成员变量并修改
//获取类对象
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!");//设置私有字段值
步骤:
- 获取类对象
- 创建类实例
- 通过getDeclaredField获得字段
- 获得字段信息
- 设置字段信息
获得类的静态成员变量并修改
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),不包括从父类继承的变量。
下一篇文章讲述代理模式。