反射 p5 反射相关使用和暴破

打印 上一主题 下一主题

主题 888|帖子 888|积分 2664

反射相关使用和暴破

通过反射创建对象


  • 方式一:调用类中的public修饰的无参构造器;
  • 方式二:调用类中的指定构造器;
  • Class类相关方法:

    • newInstance():调用类中的无参构造器,获取对应类的对象;
    • getConstructor(Class...clazz):根据参数列表,获取对应的public构造器对象;
    • getDecalaredConstructor(Class...clazz):根据参数列表,获取对应的所有构造器对象;

  • Constructor类相关方法:

    • setAccessible():暴破;
    • newInstance(Object...obj):调用构造器;

代码演示:
  1. package com.hspedu.reflection;
  2. import java.lang.reflect.Constructor;
  3. import java.lang.reflect.InvocationTargetException;
  4. /**
  5. * @author: 86199
  6. * @date: 2023/6/5 20:32
  7. * @description: 演示通过反射机制创建实例
  8. */
  9. public class ReflectCreateInstance {
  10.     public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
  11.         //先获取User类的Class对象
  12.         Class<?> userClass = Class.forName("com.hspedu.reflection.User");
  13.         //1. 通过public无参构造器构造实例
  14.         Object user = userClass.newInstance();
  15.         System.out.println("user = " + user);
  16.         //2. 通过public有参构造器构造实例
  17.         /*
  18.             此时 constructor 对象就是这个构造器
  19.             public User(String name){//public 的有参构造器
  20.                 this.name = name;
  21.             }
  22.          */
  23.         //先得到对应的构造器
  24.         Constructor<?> constructor = userClass.getConstructor(String.class);
  25.         //创建实例,传入实参
  26.         Object user1 = constructor.newInstance("小花");
  27.         System.out.println("user1 = " + user1);
  28.         //3. 通过非public有参构造器构造实例
  29.         //先得到对应的private构造器
  30.         Constructor<?> declaredConstructor = userClass.getDeclaredConstructor(String.class, int.class);
  31.         //创建实例
  32.         declaredConstructor.setAccessible(true);//暴破【暴力破解】,使用反射可以访问private构造器/方法/属性,反射面前,都是纸老虎
  33.         Object user2 = declaredConstructor.newInstance("小黑", 20);
  34.         System.out.println("user2 = " + user2);
  35.     }
  36. }
  37. class User{//User类
  38.     //属性
  39.     private String name = "大黄";
  40.     private int age = 10;
  41.     public User() {//无参构造器
  42.     }
  43.     public User(String name){//public 的有参构造器
  44.         this.name = name;
  45.     }
  46.     private User(String name, int age) {//private 有参构造器
  47.         this.name = name;
  48.         this.age = age;
  49.     }
  50.     @Override
  51.     public String toString() {
  52.         return "User [ age = " + age + ", name = " + name + " ]";
  53.     }
  54. }
  55. /*运行结果
  56. user = User [ age = 10, name = 大黄 ]
  57. user1 = User [ age = 10, name = 小花 ]
  58. user2 = User [ age = 20, name = 小黑 ]
  59. */
复制代码
通过反射访问类中成员

访问属性


  • 根据属性名获取Field对象
    Field f = clazz对象.getDeclaredField(属性名);//获取所有
    Field f = clazz对象.getField(属性名);//获取公有
  • 暴破:f.setAccessible(true)//f 是Field
  • 访问
    1. f.set(o, 值) //o 表示本类的对象
    2. System.out.println(f.get(o));//o 表示对象
    复制代码
  • 注意:如果是静态属性,则set和get中的参数o,可以写成null;
代码演示:
  1. package com.hspedu.reflection;
  2. import java.lang.reflect.Field;
  3. /**
  4. * @author: 86199
  5. * @date: 2023/6/5 21:37
  6. * @description: 演示反射操作属性
  7. */
  8. public class ReflectAccessProperty {
  9.     public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchFieldException {
  10.         //得到Student类对应的Class对象
  11.         Class<?> stuClass = Class.forName("com.hspedu.reflection.Student");
  12.         //创建对象
  13.         Object o = stuClass.newInstance();//o 的运行类型就是Student
  14.         System.out.println(o.getClass());//class com.hspedu.reflection.Student
  15.         //1. 使用反射得到age属性对象
  16.         Field age = stuClass.getField("age");//拿到公有的
  17.         age.set(o, 88);//通过反射操作属性
  18.         System.out.println(o);
  19.         System.out.println(age.get(o));//返回age的值
  20.         //2. 使用反射操作name属性
  21.         Field name = stuClass.getDeclaredField("name");
  22.         name.setAccessible(true);//对name进行暴破,可以操作私有属性
  23.         //name.set(o, "大黑");
  24.         name.set(null, "大白");//因为name是static修饰的,所以这里 o 也可以写成 null
  25.         System.out.println(o);
  26.         System.out.println(name.get(o));//获取属性值
  27.         System.out.println(name.get(null));//只有静态的才能这样用
  28.     }
  29. }
  30. class Student{//类
  31.     public int age;
  32.     private static String name;
  33.     public Student() {
  34.     }
  35.     @Override
  36.     public String toString() {
  37.         return "Student [ " +
  38.                 "age = " + age + " name = " + name +
  39.                 ']';
  40.     }
  41. }
  42. /*        运行结果
  43. class com.hspedu.reflection.Student
  44. Student [ age = 88 name = null]
  45. 88
  46. Student [ age = 88 name = 大白]
  47. 大白
  48. 大白
  49. */
复制代码
访问方法


  • 根据方法名和参数列表获取Method方法对象:
    Method m = clazz.getDeclaredMethod(方法名, XX.class);//得到本类的所有方法
    Method m = clazz.getMethod(方法名, XX.class);//得到本类的public方法
  • 暴破:m.setAccessible(true);
  • 访问:Object returnVal = m.invoke(o, 实参列表);//o就是本类的对象
  • 注意:如果是静态方法,则invoke的参数o,可以写成null;
代码演示:
  1. package com.hspedu.reflection;
  2. import java.lang.reflect.InvocationTargetException;
  3. import java.lang.reflect.Method;
  4. /**
  5. * @author: 86199
  6. * @date: 2023/6/5 21:56
  7. * @description: 演示通过反射调用方法
  8. */
  9. public class ReflectAccessMethod {
  10.     public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException {
  11.         //获取Boss类的Class对象
  12.         Class<?> bossCls = Class.forName("com.hspedu.reflection.Boss");
  13.         //创建对象
  14.         Object o = bossCls.newInstance();
  15.         //1. 调用public 的 hi 方法
  16.         //得到hi方法对象
  17. //        Method hi = bossCls.getMethod("hi", String.class);//OK
  18.         Method hi = bossCls.getDeclaredMethod("hi", String.class);//OK
  19.         hi.invoke(o, "大黄!");
  20.         //2. 调用private的say方法
  21.         //得到say方法对象
  22.         Method say = bossCls.getDeclaredMethod("say", int.class, String.class, char.class);
  23.         //因为say方法私有,所以需要先暴破
  24.         say.setAccessible(true);
  25.         System.out.println(say.invoke(o, 20, "张三", '男'));
  26.         //3. 因为say方法是static,所以可以这样调用
  27.         System.out.println(say.invoke(null, 18, "李四", '女'));
  28.         //返回值,在反射中如果方法有返回值统统返回Object,但是运行类型和方法定义的返回类型相同
  29.         //如果返回类型是void,返回null也是Object类型
  30.         Object reVal = say.invoke(null, 23, "王五", '男');
  31.         System.out.println("reVal的运行类型" + reVal.getClass());
  32.     }
  33. }
  34. class Boss{//类
  35.     public int age;
  36.     private static String name;
  37.     public Boss() {//构造器
  38.     }
  39.     private static String say(int n, String s, char c){//静态方法
  40.         return n + " " + s + " " + c;
  41.     }
  42.     public void hi(String s){//普通方法
  43.         System.out.println("hi " + s);
  44.     }
  45. }
  46. /* 运行结果
  47. hi 大黄!
  48. 20 张三 男
  49. 18 李四 女
  50. reVal的运行类型class java.lang.String
  51. */
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

小秦哥

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表