用来动态的操纵Java代码
反射机制的主要作用:
在Java程序运行时,系统为所有的对象维护一个被称为运行时类型标识。这个标识存放了一个类运行时的类型信息。在编译时,一个类对应一个Class对象,相同类型的对个实例对象会对应同一个Class对象。
获得Class类型实例的三种方式
注意:Class对象实际上表示的是一种类型,并不仅仅指类。int不是类,但int.class是一个Class类的对象
基本类型有Class对象,数组有Class对象,连关键字void也有Class对象
可以说Class类是对类型的抽象和集合
newInstance()
可以动态地创建一个类的实例
对象.getClass().newInstance()
newInstance()方法会调用默认的构造函数,如果没有默认构造函数则会抛出异常
如果想使用带参构造函数,需要用到Constructor类的newInstance方法,Constructor对象可以使用Class的实例获取,在下面讲
主要是用java.lang.reflect包中的三个类,分别用于描述类的域、方法、构造器
Field类
int getModifiers() //获取修饰限定符的编号,使用Modifier.toString()静态方法将编号装换为对应字符串 Class getType() //获取域的类型 String getName() //获取域的名称
Method类
int getModifiers() //获取修饰限定符的编号 Class getReturnType() //获取返回值类型对象 String getName() //获得方法的名称 Class[] getParameterTypes() //获得参数类型对象数组
Constructor类
int getModifiers() //获取修饰限定符的编号 String getName() //获得构造函数的名称 Class[] getParameterTypes() //获得参数类型对象数组
三种类对象的获取
使用Class类中的方法获得Field类、Method类、Constructor类
Field[] getFields() //获取本类和父类的全部公有域 Method[] getMethods() //获取本类和从父类继承的全部公有方法 Constructor[] getConstructors() //获取类中的全部公有构造函数 Field[] getDeclaredFields() //获取类中的全部域,不包括父类的 Method[] getDeclaredMethods() //获取类中的全部方法,不包括父类的 Constructor[] getDeclaredConstructors() //获取类中的全部构造函数,不包括父类的
可以使用反射机制进一步查看数据域的实际内容。
查看数据与内容的关键方法是Field类中的get方法。f为一个Field类型的对象,obj是包含f域的类的实例,那么f.get(obj)将返回obj对象中f域的实际数据。
Employee jack = new Employee("jack", 35000, 10, 1, 1998); // name money month day year Class cl = jack.getClass(); Field f = cl.getDeclaredField("name"); Object ob = f.get(jack); //如果是基本类型则会自动装箱
如果name域为private时,上面的代码会抛出IllegalAccessExecption异常,因为反射机制默认情况下受限于Java的访问控制,但是我们可以跳过安全管理器的控制,只需要调用Field、Method或Constructor对象的setAccessible(boolean)方法,将其设为true,则Field、Method或Constructor对象就可以跳过安全管理器的控制
反射机制允许调用任意方法,使用Method类的invoke()方法。其使用方法与Field类的get()方法类似
Object invoke(Object obj, Object... args)
第一个参数为执行方法的对象:m为一个Method类的对象,obj是包含m方法的类的实例
其余参数为调用m方法的参数列表
我们首先要获取一个指定的Method对象才能够执行invoke()方法,那一个指定的Method对象如何获取呢,可以有以下两种方法:
Student st = new Student("张三"); Class cl = st.getClass(); //获得Student类的getName()方法的对象 Method get = cl.getMethod("getName"); //获得Student类的setName(String)方法的对象 Method set = cl.getMethod("setName", String.class); //调用invoke执行相关的方法 String name1 = (String)get.invoke(st); set.invoke(st, "李四"); String name2 = (String)get.invoke(st); //name1:张三 name2:李四