跳转至
#java  #java安全  #反序列化 
本文阅读量 

反射篇1#

重要的反射方法#

  • 获取类的⽅方法: forName
  • 实例例化类对象的⽅方法:newInstance
  • 获取函数的⽅方法: getMethod
  • 执⾏行行函数的⽅方法: invoke

获取类的三个方法#

  1. obj.getClass(),obj是一个类的实例
  2. Clazz.class,Clazz是一个类
  3. Class.forname(),通过反射获取

Class.forname的函数重载#

forName有两个函数重载:
- Class<?> forName(String name)
- Class<?> forName(String name, **boolean** initialize, ClassLoader loader)
其中第一种方式是第二种方式的一个封装,它相当于
Class.forName(className, true, currentLoader)
其中第二个参数表示是否初始化,但是这里的初始化不是指实例的初始化(调用构造函数),而是类的初始化

类中三个"初始化"的区别#

class Test {
    {
        System.out.println("static code");
    }

    static {
        System.out.println("init top.longlone.Test class");
    }

    public Test() {
        System.out.println("init instance");
    }
}

这里有三个初始化代码,它们的区别是

  • 第一个{}中的代码会放在构造函数的super() 后面, 但在构造函数内容的前面
  • 第二个static {}中的代码是类的初始化时的代码
  • 第三个构造函数中的代码是实例初始化时的代码

所以根据上面的描述,它们的执行顺序会是2->1->3,根据这个我们也知道了forname()的第二个参数initialize代表的就是是否执行static {}中的代码,我们可以简单写段代码测试一下

package top.longlone;

class Test {
    {
        System.out.println("static code");
    }

    static {
        System.out.println("init top.longlone.Test class");
    }

    public Test() {
        System.out.println("init instance");
    }
}


public class Hello {
    public static void main(String[] args) throws ClassNotFoundException {
        Class.forName("top.longlone.Test", false, Hello.class.getClassLoader()); // 不会有输出
        Class.forName("top.longlone.Test", true, Hello.class.getClassLoader());  // 有输出
    }
}

回到页面顶部