在运行状态时,我们可以动态的获取任何一个类的字节码文件(.class文件)对象,通过这个字节码文件对象获取这个类的方法对象,构造器对象,成员变量对象等等信息。 一个类的全部组成对应一个个对象,这就是反射机制。
获取类对象有3种方式
通过字符串获取类对象: Class cls = Class.forName(包名.类名) 通过类获取类对象: Class cls =MyClass.class 通过对象获取类对象: Class cls =new MyClass().MyClass()那么如何使用获取到的构造器来创建一个对象呢? 如果获取的方法在当前是有权限可以访问的,则可以直接使用: 作用域:
作用域当前类同一package子孙类其他packagepublic√√√√protected√√√×default√√××private√××× MyClass myClass = (MyClass) constructor.newInstance();如果无法访问时执行则会抛IllegalAccessException异常。 那么我们可以通过setAccessible方法进行抑制java语言访问检查,不会抛异常,可以正常执行:
constructor.setAccessible(true); MyClass myClass = (MyClass) constructor.newInstance();得到成员变量后,给一个MyTest对象设置成员变量的值并且获取该成员变量的值:
//通过构造器new一个对象myClass MyClass myClass = (MyClass) constructor.newInstance(); //如果无权限访问则抑制java语言检查 field.setAccessible(true); field.set(myClass,3); field.get(myClass);使用成员方法:
//如果无权限访问则抑制java语言检查 method.setAccessible(true); //如果是普通成员变量,则需要传入一个对象 //如果是无参方法,那么第二个参数可以不传或者传null method.invoke(myClass); method.invoke(myClass,null); //正常传参调用方法 method.invoke(myClass,1); //如果是静态方法,第一个参数可以传null method.invoke(null,1);然后在代码中读取配置文件并且执行相关配置:
@Value("${class.name}") private String className; @Value("${method.name}") private String methodName; Class cls = Class.forName(className); Method method = cls.getMethod(methodName); Constructor constructor = cls.getConstructor(); Object obj = constructor.newInstance(); method.invoke(obj); 反射可以直接越过编译期间的泛型检查 List<String> list = Lists.newArrayList(); list.add("1"); Class cls = list.getClass(); Method method = cls.getMethod("add",Object.class); method.invoke(list,1);