01java反序列化基础

打印 上一主题 下一主题

主题 888|帖子 888|积分 2664

java反射的相关操作

一些重要的方法


  • 获取类的⽅法: forName
  • 实例化类对象的⽅法: newInstance
  • 获取函数的⽅法: getMethod
  • 执⾏函数的⽅法: invoke
  1. // eg.反射获取任意类的任意方法并执行
  2. import java.lang.reflect.Method;
  3. public class ReflectionExample {
  4.     public static void main(String[] args) {
  5.         try {
  6.             // 获取类名
  7.             Class<?> clazz = Class.forName("com.example.SomeClass");
  8.             // 获取方法名和参数类型
  9.             String methodName = "someMethod";
  10.             Class<?>[] parameterTypes = {String.class, int.class};
  11.             // 获取方法
  12.             Method method = clazz.getMethod(methodName, parameterTypes);
  13.             // 创建类的实例
  14.             Object obj = clazz.newInstance();
  15.             // 准备参数
  16.             Object[] arguments = {"example", 123};
  17.             // 执行方法
  18.             Object result = method.invoke(obj, arguments);
  19.             // 打印结果
  20.             System.out.println("Method returned: " + result);
  21.         } catch (ClassNotFoundException e) {
  22.             e.printStackTrace();
  23.         } catch (NoSuchMethodException e) {
  24.             e.printStackTrace();
  25.         } catch (IllegalAccessException e) {
  26.             e.printStackTrace();
  27.         } catch (InstantiationException e) {
  28.             e.printStackTrace();
  29.         } catch (java.lang.reflect.InvocationTargetException e) {
  30.             e.printStackTrace();
  31.         }
  32.     }
  33. }
复制代码
forName


  • forName 不是获取“类”的唯⼀途径

    • obj.getClass() 如果上下⽂中存在某个类的实例 obj ,那么我们可以直接通过
      obj.getClass() 来获取它的类
    • Test.class 如果你已经加载了某个类,只是想获取到它的 java.lang.Class 对象,那么就直接
      拿它的 class 属性即可。这个⽅法其实不属于反射。
    • Class.forName 如果你知道某个类的名字,想获取到这个类,就可以使⽤ forName 来获取

  • forName的重载

    • forName(String name)和Class forName(String name, boolean initialize, ClassLoader loader)两个重载Class
    • ClassLoader loader就是⼀个“加载器”,一样平常是一个类的完备路径,如java.lang.Runtime
    • boolean initialize决定是否进行“类初始化”,forName(String name)默认initialize=true

  • 关于类初始化的补充:下面代码的执行顺序为static{}, 构造函数的 super(),{},构造函数,static{}即为类初始化
    1. public class TrainPrint {
    2. {
    3. System.out.printf("Empty block initial %s\n", this.getClass());
    4. }
    5. static {
    6. System.out.printf("Static initial %s\n", TrainPrint.class);
    7. }
    8. public TrainPrint() {
    9. super();
    10. System.out.printf("Initial %s\n", this.getClass());
    11. }
    12. }
    复制代码
newInstance


  • class.newInstance() 的作用就是调用这个类的无参构造函数,于是乎不成功是由于:

    • 你利用的类没有无参构造函数
    • 你利用的类构造函数是私有的,例如java.lang.Runtime,可以采用类的其他静态方法获取实例

newInstance的补充getConstructor


  • Java和C++不同,C++的类必须有一个无参构造函数(显示定义或者编译器自动天生),而Java一但显示定义了任意构造函数,编译器就不会再自动天生无参构造函数,这就造成了一个问题,Java中的类大概没有无参构造函数也没有可获取实例的其他方法,此时就需要getConstructor获取有参构造函数
  1. Class clazz = Class.forName("java.lang.ProcessBuilder");
  2. clazz.getMethod("start").invoke(clazz.getConstructor(List.class).newInstance(
  3. Arrays.asList("calc.exe")));
  4. );
复制代码
关于类的私有方法


  • 类的私有方法可以通过getDeclared 系列的反射调用,与普通的 getMethod 、 getConstructor 区别是:

    • getMethod 系列方法获取的是当前类中所有公共方法,包括从父类继续的方法
    • getDeclaredMethod 系列方法获取的是当前类中“声明”的方法,是实在写在这个类里的,包括私
      有的方法,但从父类里继续来的就不包含了
    1. Class clazz = Class.forName("java.lang.Runtime");
    2. Constructor m = clazz.getDeclaredConstructor();
    3. // setAccessible(true)修改作用域是必须得
    4. m.setAccessible(true);
    5. clazz.getMethod("exec", String.class).invoke(m.newInstance(), "calc.exe");
    复制代码
反射的一些特性


  • 无需import类
  • 可以访问私有方法
不同语言的序列化对比

PHP序列化

[code]
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

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

本版积分规则

石小疯

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

标签云

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