1.反射

  1. 为什么需要反射
    在不修改源码的情况下,控制程序
    在不知道类结构信息的情况下,也可以获取类的结构信息,方便后续的hook
    可以突破访问修饰符的限制
  2. 反射入门
    加载类
    得到方法对象
    调用方法,如果是实例方法,还需要创建一个实例

    1. import java.lang.reflect.Method;
    2. public class Hello {
    3. public static void main(String[] args) throws Exception{
    4. String class_test= "class_test";
    5. String MethodNaMe="b";
    6. Class<?> cls = Class.forName(class_test);//找到一个类
    7. Method method = cls.getMethod(MethodNaMe);//找到一个方法
    8. method.invoke(null);//执行方法;static方法可以使用null;其他的后续补充
    9. }}
    10. class class_test{
    11. public static int b() {
    12. System.out.println("测试文本1");
    13. return 0;
    14. }
    15. public int age =0;
    16. public class_test(int age) {
    17. System.out.println("测试文本2222");
    18. this.age = age;
    19. }
    20. }

    2.Class类

  3. Class也是类,因此也继承Object类(接口没有继承Object)

  4. Class类对象是通过ClassLoader的loadClass加载的
  5. Class类对象只加载一次,除非ClassLoader不一样(具体看代码)
  6. 通过Class可以完整地得到一个类的完整结构,通过一系列API
  7. Class对象是存放在堆的,类的字节码二进制数据,是放在方法区的,有的也称为类的元数据(包括方法代码, 变量名,方法名,访问权限等等)

    1. import java.lang.reflect.Method;
    2. public class Hello {
    3. public static void main(String[] args) throws Exception{
    4. String class_test= "class_test";
    5. String MethodNaMe="b";
    6. new class_test(1).b();
    7. Class<?> cls = Class.forName(class_test);
    8. Method method = cls.getMethod(MethodNaMe);
    9. method.invoke(null);
    10. /*
    11. 两种方法,如果我们执行了 new class_test(1).b();来实现b方法,
    12. 那么method.invoke(null);这种方法就不会通过ClassLoader的loadClass加载的
    13. 反之,我们没有执行第一个方法,直接执行第二个方法,那么method.invoke(null)就会通过ClassLoader的loadClass加载的
    14. */
    15. }}
    16. class class_test{
    17. public static int b() {
    18. System.out.println("测试文本1");
    19. return 0;
    20. }
    21. public int age =0;
    22. public class_test(int age) {
    23. System.out.println("测试文本2222");
    24. this.age = age;
    25. }
    26. }

    3. Class类对象的获取方式(重点)

    a) Class.forName(…)
    b) 类.class 多用于参数传递
    c) 对象.getClass()
    d) ClassLoader.loadClass(…)
    e) 基本数据类型的Class类对象获取 int.class Integer.TYPE
    f) 包装类的Class类对象获取 Integer.classimage.png

    4.哪些有Class对象

  8. 获取内部类

    1. public class Hello {
    2. public static void main(String[] args) throws Exception{
    3. System.out.println(Class.forName("class_test$demo"));//class class_test$demo
    4. }}//Class.forName(类的全路径,极包名+类名)
    5. class class_test{
    6. public int age =0;
    7. public class_test(int age) {
    8. System.out.println("测试文本2222");
    9. this.age = age;
    10. }
    11. class demo {
    12. }
    13. }
  9. 匿名类内部类

    1. public class Hello {
    2. public static void main(String[] args) throws Exception{
    3. new demo1() {//同目录下创建一个接口
    4. public void test(){
    5. System.out.println("-------------------------");
    6. };
    7. }.test();//匿名类内部类
    8. System.out.println(Class.forName("Hello$1"));//class Hello$1
    9. }}
  10. 接口,数组

    1. public class Hello {
    2. public static void main(String[] args) throws Exception{
    3. //同目录下创建一个接口
    4. System.out.println("-------------------------");//匿名类内部类
    5. System.out.println(demo1.class);//interface demo1 接口
    6. System.out.println(Integer.class);//class java.lang.Integer 包装类
    7. System.out.println(Void.class);//class java.lang.Void
    8. String[] A=new String[]{"aaaa"};
    9. String[][] A1=new String[][]{{"aaaa"}};
    10. System.out.println(A.getClass());//class [[Ljava.lang.String;
    11. System.out.println(String[].class);//class [[Ljava.lang.String;
    12. System.out.println(String[][].class);//class [[Ljava.lang.String;
    13. }}

    4.反射创建对象
    a) 无参构造器
    b) 有参构造器
    c) 私有构造器

    1. import java.lang.reflect.Constructor;
    2. public class Hello {
    3. public static void main(String[] args) throws Exception{
    4. Class<?> a1 = Class.forName("test");
    5. Object o = a1.newInstance();//newInstance调用无参构造器
    6. System.out.println(o.getClass());
    7. Constructor<?> constructor = a1.getConstructor(String.class, int.class);//有参构造器
    8. constructor.newInstance("123",50);
    9. Constructor<?> o2222 = a1.getDeclaredConstructor(String.class);//访问私有构造器
    10. o2222.setAccessible(true);//作用:加上即可访问私有方法
    11. o2222.newInstance("1233");
    12. }}
    13. class test{
    14. public String name;
    15. public int age;
    16. public test() {
    17. System.out.println("================");
    18. }
    19. public test(String name, int age) {
    20. System.out.println("*****************");
    21. this.name = name;
    22. this.age = age;
    23. }
    24. private test(String name) {
    25. System.out.println("-------------------");
    26. this.name = name;
    27. }
    28. }
  11. 反射操作属性

a) 获取属性(四种)
b) 设置属性
c) 私有属性
d) 如果是静态属性,第一个参数可以给null

  1. import java.lang.reflect.Constructor;
  2. import java.lang.reflect.Field;
  3. public class Hello {
  4. public static void main(String[] args) throws Exception{
  5. Class<?> a1 = Class.forName("test");
  6. Constructor<?> o2222 = a1.getDeclaredConstructor(String.class);//访问私有构造器
  7. o2222.setAccessible(true);//作用:加上即可访问私有方法
  8. Object o1 = o2222.newInstance("1233");
  9. Field Fieldname = a1.getField("name");
  10. System.out.println(Fieldname.get(o1));//取值
  11. Fieldname.set(o1,"修改文本");//改值
  12. System.out.println(Fieldname.get(o1));//取值
  13. Field Fieldsex = a1.getDeclaredField("sex");
  14. Fieldsex.setAccessible(true);
  15. Fieldsex.set(o1,true);
  16. //Fieldsex.set(null,true); 静态属性的时候可以设置成为null
  17. boolean sex = (boolean) Fieldsex.get(o1);
  18. System.out.println(sex);
  19. }}
  20. class test{
  21. public String name;
  22. public int age;
  23. private static boolean sex;
  24. public test() {
  25. System.out.println("================");
  26. }
  27. public test(String name, int age) {
  28. System.out.println("*****************");
  29. this.name = name;
  30. this.age = age;
  31. }
  32. private test(String name) {
  33. System.out.println("-------------------");
  34. this.name = name;
  35. }
  36. }
  1. 反射操作方法

a) 获取方法(四种)
b) 调用方法
c) 私有方法
d) 如果是静态方法,第一个参数可以给null

  1. import java.lang.reflect.Constructor;
  2. import java.lang.reflect.Method;
  3. public class Hello {
  4. public static void main(String[] args) throws Exception{
  5. Class<?> a1 = Class.forName("test");
  6. Constructor<?> o2222 = a1.getDeclaredConstructor(String.class);
  7. o2222.setAccessible(true);
  8. Object o1 = o2222.newInstance("1233");
  9. Method test_method = a1.getMethod("test_method", String.class);
  10. Object invoke = test_method.invoke(o1, "55555");
  11. Method test_method_private = a1.getDeclaredMethod("test_method_private", String.class);
  12. test_method_private.setAccessible(true);
  13. Object invoke1 = (String)test_method_private.invoke(o1, "555");
  14. System.out.println(invoke1);
  15. }}
  16. class test{
  17. public String name;
  18. public int age;
  19. private static boolean sex;
  20. public test() {
  21. System.out.println("================");
  22. }
  23. public test(String name, int age) {
  24. System.out.println("*****************");
  25. this.name = name;
  26. this.age = age;
  27. }
  28. public static String test_method(String name) {
  29. return "2222222"+" "+name;
  30. }
  31. private test(String name) {
  32. System.out.println("-------------------");
  33. this.name = name;
  34. }
  35. private String test_method_private(String name) {
  36. return "69696 "+name;
  37. }
  38. }

其他方法:

  1. java.lang.reflect.Field类
    a) getModifiers: 以int形式返回修饰符
    a) getType: 以Class形式返回类型
    a) getName: 返回属性名
  2. java.lang.reflect.Method类
    a) getModifiers: 以int形式返回修饰符
    a) getReturnType: 以Class形式获取返回类型
    a) getName: 返回方法名
    a) getParameterTypes: 以Class[]返回参数类型数组
  3. java.lang.reflect.Constructor类
    a) getModifiers: 以int形式返回修饰符
    a) getName: 返回构造器名(全类名)
    a) getParameterTypes: 以Class[]返回参数类型数组
    a) newInstance

    1. import java.lang.reflect.Method;
    2. public class Hello {
    3. public static void main(String[] args) throws Exception{
    4. Class<?> a1 = Class.forName("test");
    5. Method[] declaredMethods = a1.getDeclaredMethods();
    6. for (Method declaredMethod : declaredMethods) {
    7. System.out.println(declaredMethod);
    8. }
    9. }}
    10. class test{
    11. public String name;
    12. public int age;
    13. private static boolean sex;
    14. public test() {
    15. System.out.println("================");
    16. }
    17. public test(String name, int age) {
    18. System.out.println("*****************");
    19. this.name = name;
    20. this.age = age;
    21. }
    22. public static String test_method(String name) {
    23. return "2222222"+" "+name;
    24. }
    25. private test(String name) {
    26. System.out.println("-------------------");
    27. this.name = name;
    28. }
    29. private String test_method_private(String name) {
    30. return "69696 "+name;
    31. }
    32. private String a3333(String name) {
    33. return "69696 "+name;
    34. }
    35. }