1.反射
- 为什么需要反射
在不修改源码的情况下,控制程序
在不知道类结构信息的情况下,也可以获取类的结构信息,方便后续的hook
可以突破访问修饰符的限制 反射入门
加载类
得到方法对象
调用方法,如果是实例方法,还需要创建一个实例import java.lang.reflect.Method;public class Hello {public static void main(String[] args) throws Exception{String class_test= "class_test";String MethodNaMe="b";Class<?> cls = Class.forName(class_test);//找到一个类Method method = cls.getMethod(MethodNaMe);//找到一个方法method.invoke(null);//执行方法;static方法可以使用null;其他的后续补充}}class class_test{public static int b() {System.out.println("测试文本1");return 0;}public int age =0;public class_test(int age) {System.out.println("测试文本2222");this.age = age;}}
2.Class类
Class也是类,因此也继承Object类(接口没有继承Object)
- Class类对象是通过ClassLoader的loadClass加载的
- Class类对象只加载一次,除非ClassLoader不一样(具体看代码)
- 通过Class可以完整地得到一个类的完整结构,通过一系列API
Class对象是存放在堆的,类的字节码二进制数据,是放在方法区的,有的也称为类的元数据(包括方法代码, 变量名,方法名,访问权限等等)
import java.lang.reflect.Method;public class Hello {public static void main(String[] args) throws Exception{String class_test= "class_test";String MethodNaMe="b";new class_test(1).b();Class<?> cls = Class.forName(class_test);Method method = cls.getMethod(MethodNaMe);method.invoke(null);/*两种方法,如果我们执行了 new class_test(1).b();来实现b方法,那么method.invoke(null);这种方法就不会通过ClassLoader的loadClass加载的反之,我们没有执行第一个方法,直接执行第二个方法,那么method.invoke(null)就会通过ClassLoader的loadClass加载的*/}}class class_test{public static int b() {System.out.println("测试文本1");return 0;}public int age =0;public class_test(int age) {System.out.println("测试文本2222");this.age = age;}}
3. Class类对象的获取方式(重点)
a) Class.forName(…)
b) 类.class 多用于参数传递
c) 对象.getClass()
d) ClassLoader.loadClass(…)
e) 基本数据类型的Class类对象获取 int.class Integer.TYPE
f) 包装类的Class类对象获取 Integer.class
4.哪些有Class对象
获取内部类
public class Hello {public static void main(String[] args) throws Exception{System.out.println(Class.forName("class_test$demo"));//class class_test$demo}}//Class.forName(类的全路径,极包名+类名)class class_test{public int age =0;public class_test(int age) {System.out.println("测试文本2222");this.age = age;}class demo {}}
匿名类内部类
public class Hello {public static void main(String[] args) throws Exception{new demo1() {//同目录下创建一个接口public void test(){System.out.println("-------------------------");};}.test();//匿名类内部类System.out.println(Class.forName("Hello$1"));//class Hello$1}}
接口,数组
public class Hello {public static void main(String[] args) throws Exception{//同目录下创建一个接口System.out.println("-------------------------");//匿名类内部类System.out.println(demo1.class);//interface demo1 接口System.out.println(Integer.class);//class java.lang.Integer 包装类System.out.println(Void.class);//class java.lang.VoidString[] A=new String[]{"aaaa"};String[][] A1=new String[][]{{"aaaa"}};System.out.println(A.getClass());//class [[Ljava.lang.String;System.out.println(String[].class);//class [[Ljava.lang.String;System.out.println(String[][].class);//class [[Ljava.lang.String;}}
4.反射创建对象
a) 无参构造器
b) 有参构造器
c) 私有构造器import java.lang.reflect.Constructor;public class Hello {public static void main(String[] args) throws Exception{Class<?> a1 = Class.forName("test");Object o = a1.newInstance();//newInstance调用无参构造器System.out.println(o.getClass());Constructor<?> constructor = a1.getConstructor(String.class, int.class);//有参构造器constructor.newInstance("123",50);Constructor<?> o2222 = a1.getDeclaredConstructor(String.class);//访问私有构造器o2222.setAccessible(true);//作用:加上即可访问私有方法o2222.newInstance("1233");}}class test{public String name;public int age;public test() {System.out.println("================");}public test(String name, int age) {System.out.println("*****************");this.name = name;this.age = age;}private test(String name) {System.out.println("-------------------");this.name = name;}}
反射操作属性
a) 获取属性(四种)
b) 设置属性
c) 私有属性
d) 如果是静态属性,第一个参数可以给null
import java.lang.reflect.Constructor;import java.lang.reflect.Field;public class Hello {public static void main(String[] args) throws Exception{Class<?> a1 = Class.forName("test");Constructor<?> o2222 = a1.getDeclaredConstructor(String.class);//访问私有构造器o2222.setAccessible(true);//作用:加上即可访问私有方法Object o1 = o2222.newInstance("1233");Field Fieldname = a1.getField("name");System.out.println(Fieldname.get(o1));//取值Fieldname.set(o1,"修改文本");//改值System.out.println(Fieldname.get(o1));//取值Field Fieldsex = a1.getDeclaredField("sex");Fieldsex.setAccessible(true);Fieldsex.set(o1,true);//Fieldsex.set(null,true); 静态属性的时候可以设置成为nullboolean sex = (boolean) Fieldsex.get(o1);System.out.println(sex);}}class test{public String name;public int age;private static boolean sex;public test() {System.out.println("================");}public test(String name, int age) {System.out.println("*****************");this.name = name;this.age = age;}private test(String name) {System.out.println("-------------------");this.name = name;}}
- 反射操作方法
a) 获取方法(四种)
b) 调用方法
c) 私有方法
d) 如果是静态方法,第一个参数可以给null
import java.lang.reflect.Constructor;import java.lang.reflect.Method;public class Hello {public static void main(String[] args) throws Exception{Class<?> a1 = Class.forName("test");Constructor<?> o2222 = a1.getDeclaredConstructor(String.class);o2222.setAccessible(true);Object o1 = o2222.newInstance("1233");Method test_method = a1.getMethod("test_method", String.class);Object invoke = test_method.invoke(o1, "55555");Method test_method_private = a1.getDeclaredMethod("test_method_private", String.class);test_method_private.setAccessible(true);Object invoke1 = (String)test_method_private.invoke(o1, "555");System.out.println(invoke1);}}class test{public String name;public int age;private static boolean sex;public test() {System.out.println("================");}public test(String name, int age) {System.out.println("*****************");this.name = name;this.age = age;}public static String test_method(String name) {return "2222222"+" "+name;}private test(String name) {System.out.println("-------------------");this.name = name;}private String test_method_private(String name) {return "69696 "+name;}}
其他方法:
- java.lang.reflect.Field类
a) getModifiers: 以int形式返回修饰符
a) getType: 以Class形式返回类型
a) getName: 返回属性名 - java.lang.reflect.Method类
a) getModifiers: 以int形式返回修饰符
a) getReturnType: 以Class形式获取返回类型
a) getName: 返回方法名
a) getParameterTypes: 以Class[]返回参数类型数组 java.lang.reflect.Constructor类
a) getModifiers: 以int形式返回修饰符
a) getName: 返回构造器名(全类名)
a) getParameterTypes: 以Class[]返回参数类型数组
a) newInstanceimport java.lang.reflect.Method;public class Hello {public static void main(String[] args) throws Exception{Class<?> a1 = Class.forName("test");Method[] declaredMethods = a1.getDeclaredMethods();for (Method declaredMethod : declaredMethods) {System.out.println(declaredMethod);}}}class test{public String name;public int age;private static boolean sex;public test() {System.out.println("================");}public test(String name, int age) {System.out.println("*****************");this.name = name;this.age = age;}public static String test_method(String name) {return "2222222"+" "+name;}private test(String name) {System.out.println("-------------------");this.name = name;}private String test_method_private(String name) {return "69696 "+name;}private String a3333(String name) {return "69696 "+name;}}
