本篇博客介绍java中最强大的技术:反射;反射包括以下技术:
- 根据一个字符串得到一个类的对象
- 获取一个类的所有公用或私有、静态或实例的字段、方法、属性
- 对泛型的反射
根据一个字符串得到一个类
① getClass:通过一个对象获取它的类型,类型用class表示
String str = "hello";
Class num = str.getClass();
Log.e("----->>", ">>>" + num);
打印为:class java.lang.String
② Class.forName
这个方法用的最多,通过一个字符串获取类型,这个字符串由类的命名空间和类的名称组成,而通过getSuperclass方法,获取对象的父类型
try {
Class num02 = Class.forName("android.widget.Button");
Class num03 = Class.forName("java.lang.String");
Class num04 = num02.getSuperclass();
Log.e(TAG, "02>" + num02);
Log.e(TAG, "03>>" + num03);
Log.e(TAG, "04>>" + num04);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
打印为:
android.widget.Button、java.lang.String、android.widget.TextView
③ 每个类都有class属性,可以得到这个类的类型
Class c01 = String.class;
Class c02 = MainActivity.class;
Class c03 = MainActivity.TAG.getClass();
Log.e(TAG, "-02-->>" + c01 + ";;;>>>>" + c02 + "----->>" + c03);
打印为:class java.lang.String、class com.my.hookdemo.MainActivity、class java.lang.String
④基本类型:如Boolean等都有type属性,可以得到这个基本类型的类型:
扫描二维码关注公众号,回复:
9391794 查看本文章
Class c01 = Boolean.TYPE;
Class c02 = Byte.TYPE;
Log.e(TAG, "-02-->>" + c01 + ";;;>>>>" + c02);
打印为:boolean、byte
下面贴上代码,封装了一些操作包括:反射构造函数、反射并调用private方法、反射并调用public方法、反射并调用public属性、设置一个字段,代码中有详细说明
package com.my.hookdemo.hook;
import android.util.Log;
public class TestClass {
public String adds;
private String names;
public TestClass() {
}
private TestClass(String names) {
names = names;
}
private TestClass(String a, String c) {
adds = a;
names = c;
}
public String getAdds() {
return adds;
}
public void setAdds(String adds) {
this.adds = adds;
}
public String getNames() {
return names;
}
public void setNames(String names) {
this.names = names;
}
private String doSomeThing() {
return "hello world 的私有方法";
}
public void testMothod(String msg) {
Log.e("---打印的值->>", "00>>>" + msg);
}
public static int testStatic(int values) {
return values;
}
private void callPrivate(String key) {
Log.e("---打印的值->>", "04>>>" + key);
}
}
封装的Reflnvoke类
package com.my.hookdemo.hook;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Reflnvoke {
/**
* 反射出构造函数
* @param className 类的名字
* @param pareTypes 参数的类型
* @param pareValues 参数的值
* @return object 对象的实例
*
* */
public static Object createObject(String className, Class[] pareTypes, Object[] pareValues) {
try {
Class r = Class.forName(className);
Constructor ctor = r.getDeclaredConstructor(pareTypes);
ctor.setAccessible(true);
return ctor.newInstance(pareValues);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 调用private方法
*
* @param obj 对应类的反射object
* @param methodName 方法名字
* @param pareTypes 参数类型
* @param pareValue 参数值
*
* @return 返回方法的返回值,如果返回值为null,即返回为null,如果返回为string,则返回为string
* */
public static Object invokeInstanceMethod(Object obj, String methodName, Class[] pareTypes, Object[] pareValue) {
if (obj == null) {
return null;
}
try {
Method method = obj.getClass().getDeclaredMethod(methodName, pareTypes);//在指定类中获取指定方法
method.setAccessible(true);
return method.invoke(obj, pareValue);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 调用静态方法
* @param className 类的名字
* @param methgod_name 方法名字
* @param pareTypes 参数类型
* @param pareValues 参数值
*
* @return 返回方法的返回值,如果返回值为null,即返回为null,如果返回为string,则返回为string
* */
public static Object invokeStaticMethod(String className, String methgod_name, Class[] pareTypes, Object[] pareValues) {
try {
Class obj_class = Class.forName(className);
Method method = obj_class.getDeclaredMethod(methgod_name, pareTypes);
method.setAccessible(true);
return method.invoke(null, pareValues);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* 获取类的public 属性的值
* @param className class的名字
* @param object 对应的object
* @param fieldName 对应的public 属性值
*
* */
public static Object getFieldObject(String className, Object object, String fieldName) {
try {
Class obj_class = Class.forName(className);
Field field = obj_class.getDeclaredField(fieldName);
field.setAccessible(true);
return field.get(object);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
//设置一个字段
public static void setFieldObject(String className, Object obj, String fieldName, Object fieldValue) {
try {
Class obj_class = Class.forName(className);
Field field = obj_class.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(obj, fieldValue);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Object getStaticFieldObject(String className, String field) {
return getFieldObject(className, null, field);
}
public static void setStaticFieldObject(String className, String fieldName, Object fieldValue) {
setFieldObject(className, null, fieldName, fieldValue);
}
// public static Object getFieldObject(Object object, String fieldName) {
// return getFieldObject(object.getClass(), object, fieldName);
// }
}
调用处:
try {
Class r = Class.forName("com.my.hookdemo.hook.TestClass");
Class[] p3 = {String.class, String.class};
Object[] v3 = {"11", "stone"};
Object object = Reflnvoke.createObject("com.my.hookdemo.hook.TestClass", p3, v3);
TestClass testClass = (TestClass) object;
testClass.testMothod("hello world");//调用public方法
//调用soSomeThing私有方法,返回string类型,不传递参数
String object02 = (String) Reflnvoke.invokeInstanceMethod(object, "doSomeThing", null, null);
Log.e("---打印的值->>", "01>>>" + object02);
Class[] p4 = {int.class};
Object[] v4 = {7800};
//调用testStatic静态方法,参数类型为p4,参数方法为v4
int values = (int) Reflnvoke.invokeStaticMethod("com.my.hookdemo.hook.TestClass", "testStatic", p4, v4);
Log.e("---打印的值->>", "02>>>" + values);
//设置public属性adds为"你好"
Reflnvoke.setFieldObject("com.my.hookdemo.hook.TestClass", object, "adds", "你好");
String name = (String) Reflnvoke.getFieldObject("com.my.hookdemo.hook.TestClass", object, "adds");
Log.e("---打印的值->>", "03>>>" + name);
Class[] p5 = {String.class};
Object[] v5 = {"调用了私有方法"};
Reflnvoke.invokeInstanceMethod(object, "callPrivate", p5, v5);
Reflnvoke.setFieldObject("com.my.hookdemo.hook.TestClass", object, "names", "设置private属性");
String names = (String) Reflnvoke.getFieldObject("com.my.hookdemo.hook.TestClass", object, "names");
Log.e("---打印的值->>", "05>>>" + names);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
打印的结果为:
12-26 09:10:44.048 2308-2308/com.my.hookdemo E/---打印的值->>: 00>>>hello world
12-26 09:10:44.056 2308-2308/com.my.hookdemo E/---打印的值->>: 01>>>hello world 的私有方法
12-26 09:10:44.056 2308-2308/com.my.hookdemo E/---打印的值->>: 02>>>7800
12-26 09:10:44.056 2308-2308/com.my.hookdemo E/---打印的值->>: 03>>>你好
12-26 09:10:44.056 2308-2308/com.my.hookdemo E/---打印的值->>: 04>>>调用了私有方法
12-26 09:10:44.056 2308-2308/com.my.hookdemo E/---打印的值->>: 05>>>设置private属性
封装的工具类可以直接拿过来用