java反射的相关操作
一些重要的方法
- 获取类的⽅法: forName
- 实例化类对象的⽅法: newInstance
- 获取函数的⽅法: getMethod
- 执⾏函数的⽅法: invoke
- // eg.反射获取任意类的任意方法并执行
- import java.lang.reflect.Method;
- public class ReflectionExample {
- public static void main(String[] args) {
- try {
- // 获取类名
- Class<?> clazz = Class.forName("com.example.SomeClass");
- // 获取方法名和参数类型
- String methodName = "someMethod";
- Class<?>[] parameterTypes = {String.class, int.class};
- // 获取方法
- Method method = clazz.getMethod(methodName, parameterTypes);
- // 创建类的实例
- Object obj = clazz.newInstance();
- // 准备参数
- Object[] arguments = {"example", 123};
- // 执行方法
- Object result = method.invoke(obj, arguments);
- // 打印结果
- System.out.println("Method returned: " + result);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (java.lang.reflect.InvocationTargetException e) {
- e.printStackTrace();
- }
- }
- }
复制代码 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{}即为类初始化
- public class TrainPrint {
- {
- System.out.printf("Empty block initial %s\n", this.getClass());
- }
- static {
- System.out.printf("Static initial %s\n", TrainPrint.class);
- }
- public TrainPrint() {
- super();
- System.out.printf("Initial %s\n", this.getClass());
- }
- }
复制代码 newInstance
- class.newInstance() 的作用就是调用这个类的无参构造函数,于是乎不成功是由于:
- 你利用的类没有无参构造函数
- 你利用的类构造函数是私有的,例如java.lang.Runtime,可以采用类的其他静态方法获取实例
newInstance的补充getConstructor
- Java和C++不同,C++的类必须有一个无参构造函数(显示定义或者编译器自动天生),而Java一但显示定义了任意构造函数,编译器就不会再自动天生无参构造函数,这就造成了一个问题,Java中的类大概没有无参构造函数也没有可获取实例的其他方法,此时就需要getConstructor获取有参构造函数
- Class clazz = Class.forName("java.lang.ProcessBuilder");
- clazz.getMethod("start").invoke(clazz.getConstructor(List.class).newInstance(
- Arrays.asList("calc.exe")));
- );
复制代码 关于类的私有方法
- 类的私有方法可以通过getDeclared 系列的反射调用,与普通的 getMethod 、 getConstructor 区别是:
- getMethod 系列方法获取的是当前类中所有公共方法,包括从父类继续的方法
- getDeclaredMethod 系列方法获取的是当前类中“声明”的方法,是实在写在这个类里的,包括私
有的方法,但从父类里继续来的就不包含了
- Class clazz = Class.forName("java.lang.Runtime");
- Constructor m = clazz.getDeclaredConstructor();
- // setAccessible(true)修改作用域是必须得
- m.setAccessible(true);
- clazz.getMethod("exec", String.class).invoke(m.newInstance(), "calc.exe");
复制代码 反射的一些特性
不同语言的序列化对比
PHP序列化
[code] |