java中的基本反射回顾
想了解Hook技术反射永远是绕不过去的拦路虎,所以打算复习一下简单的java反射,仅以此文作为复习和熟悉markdown的语法。本文主要会涉及的反射实例如下
- 反射类的私有属性
- 反射类的私有方法
- 反射类的私有构造方法
- 反射内部类的私有属性
- 反射内部类的私有方法
首先准备一个被反射的类
下面这个类包含了我们所有要反射的方法和属性
public class ReflectTest {
private String pStr = "普通类的私有属性";
public ReflectTest() {
}
private ReflectTest(String pStr) {
this.pStr = pStr;
}
public void logPStr(){
Log.e("TAG", "logPStr: ==========="+pStr );
}
private void priLogPStr(){
Log.e("TAG", "priLogPStr: ==========="+pStr );
}
class PcText {
private String pcStr = "内部类中的私有属性";
private void showLog(){
Log.e("TAG", "showLog: =========内部类中的私有方法" );
}
}
}
一.反射类的私有属性
方法
/**
* 反射类的私有属性
*/
private void reflectPrivateAttribute(){
try {
ReflectTest reflectTest = new ReflectTest();
//装载要反射的类
Class<?> aClass = Class.forName("com.example.hookdemoapp.ReflectTest");
//通过getDeclaredField获取的属性包含所有修饰
//如果用getField则只能获取public的属性
Field field = aClass.getDeclaredField("pStr");
//设置改属性可以被访问
field.setAccessible(true);
Log.e("TAG", "pStr: 1======================" +field.get(reflectTest));
//set方法第一个参数为实例,第二个参数为属性的目标值
field.set(reflectTest, "修改后的私有属性");
Log.e("TAG", "pStr: 2======================" +field.get(reflectTest));
} catch (Exception e) {
e.printStackTrace();
}
}
执行结果如下,方法的注释写的很清楚,这里不在赘述。
E/TAG: pStr: 1======================普通类的私有属性
E/TAG: pStr: 2======================修改后的私有属性
二.反射类的私有方法
方法
/**
* 反射类的私有方法
*/
private void reflectPrivateConstructor(){
try {
ReflectTest reflectTest = new ReflectTest();
//装载要反射的类
Class<?> aClass = Class.forName("com.example.hookdemoapp.ReflectTest");
//通过getDeclaredMethod获取的方法包含所有修饰
//如果用getMethod则只能获取public的方法
Method method = aClass.getDeclaredMethod("priLogPStr");
//设置成可以被访问
method.setAccessible(true);
//invoke为执行方法,第一个参数是类的实例,后面的参数为方法的传参,没有参数可以传null
method.invoke(reflectTest, null);
} catch (Exception e) {
e.printStackTrace();
}
}
执行结果如下
E/TAG: priLogPStr: ===========普通类的私有属性
三.反射类的私有构造方法
方法
/**
* 反射类的私有构造方法创建对象
*/
private void reflectPrivateMethod(){
try {
//装载要反射的类
Class<?> aClass = Class.forName("com.example.hookdemoapp.ReflectTest");
//参数类型类的集合
Class[] p = {String.class};
//反射带有一个参数的构造方法
Constructor<?> declaredConstructor1 = aClass.getDeclaredConstructor(p);
declaredConstructor1.setAccessible(true);
//传入参数创建对象
Object obj = declaredConstructor1.newInstance("通过反射私有构造方法创建对象");
//通过getDeclaredMethod获取的方法包含所有修饰
//如果用getMethod则只能获取public的方法
Method method = aClass.getDeclaredMethod("priLogPStr");
//设置成可以被访问
method.setAccessible(true);
//invoke为执行方法,第一个参数是类的实例,后面的参数为方法的传参,没有参数可以传null
method.invoke(obj, null);
} catch (Exception e) {
e.printStackTrace();
}
}
执行结果如下
priLogPStr: ===========通过反射私有构造方法创建对象
四.反射内部类的私有属性
方法
/**
* 反射内部类的私有属性
*/
private void reflectICPrivateAttribute(){
try {
ReflectTest reflectTest = new ReflectTest();
//装载要反射的类,涉及内部类要用"类$内部类"的形式
Class<?> aClass = Class.forName("com.example.hookdemoapp.ReflectTest$PcText");
//反射内部类的无参构造时需要传入外部类的class
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(ReflectTest.class);
declaredConstructor.setAccessible(true);
//传入参数创建对象,这里为了方便参数没通过反射创建
Object obj = declaredConstructor.newInstance(reflectTest);
//通过getDeclaredField获取的属性包含所有修饰
//如果用getField则只能获取public的属性
Field field = aClass.getDeclaredField("pcStr");
//设置成可以被访问
field.setAccessible(true);
Log.e("TAG", "reflectICPrivateAttribute: =================="+field.get(obj) );
} catch (Exception e) {
e.printStackTrace();
}
}
执行结果如下
E/TAG: reflectICPrivateAttribute: ==================内部类中的私有属性
五.反射内部类的私有方法
方法
/**
* 反射内部类的私有方法
*/
private void reflectICPrivateMethod(){
try {
ReflectTest reflectTest = new ReflectTest();
//装载要反射的类,涉及内部类要用"类$内部类"的形式
Class<?> aClass = Class.forName("com.example.hookdemoapp.ReflectTest$PcText");
//反射内部类的无参构造时需要传入外部类的class
Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(ReflectTest.class);
declaredConstructor.setAccessible(true);
//传入参数创建对象,这里为了方便参数没通过反射创建
Object obj = declaredConstructor.newInstance(reflectTest);
//通过getDeclaredMethod获取的方法包含所有修饰
//如果用getMethod则只能获取public的方法
Method method = aClass.getDeclaredMethod("showLog");
//设置成可以被访问
method.setAccessible(true);
method.invoke(obj, null);
} catch (Exception e) {
e.printStackTrace();
}
}
执行结果如下
E/TAG: showLog: =========内部类中的私有方法
结语
简单的反射涉及的方法并不多,下一步主备温故一下动态代理相关内容以便于后面了解hook技术。