JAVA反射机制是在运行状态中,对任意一个类,都能知道这个类的所有属性和方法,对于任意一个对象,都能调用他的任意一个方法和属性(动态获取指定类及其成员,并运行其中的内容)
使用反射,可以在运行时对类Class、构造方法Constructor、普通方法Method、字段Field进行操作
应用程序已经运行,无法在其中进行new对象的建立,就无法使用对象。这时可以根据配置文件的类全名(带有包名)去找对应的字节码文件,并加载进内存,并创建该类对象实例。这就需要使用反射技术完成
获取class对象的三种方式
一、 采用继承自Object类的getClass()方法 有点不方便 需要用到该类并创建该类的对象 再调用getClass()方法完成
Person p = new Person();
Class classzz = p.getClass();
二、 采用每个类型都具备的class静态属性 比第一个简单 但还是必须要使用到该类
Class classzz = Person.class;
三、 采用Class类中的静态forName(className)方法 不需要直接使用具体的类 只需要知道该类的全名 名字可以作为参数传递 可以提高扩展性 最常用
Class classzz = Class.forName("cn.a2490.test.Person"); 注:必须使用全名(包含包名)
API
获取classzz对象对应的类的全部构造器
Constructor[] ctros = classzz.getDeclaredConstructors();
获取classzz对象对应的类的public权限的构造器
Constructor[] constructors = classzz.getConstructors();
获取classzz对象对应的类的public方法
Method[] methods = classzz.getMethods();
获取classzz对象对应类的指定的方法 方法名 参数的class对象
Method method = classzz.getMethod("setName", String.class);
获取classzz对象对应类的全部注解
Annotation[] annotations = classzz.getAnnotations();
获取classzz对象对应的类的全部内部类
Class[] inClasses = classzz.getDeclaredClasses();
使用Class.forName()方法加载Inner内部类
Class inClasszz = Class.forName("Person$Inner");
获取classzz对象对应的类的外部类
Class outClass = classzz.getDeclaringClass();
获取classzz对象对应的类的包
Package classPackage = classzz.getPackage();
获取classzz对象对应的类的父类
Class superclass = classzz.getSuperclass();
应用
class对象可以获得对应类的方法(Method)、构造器(Constructor)、成员变量(Field)。这三个类都实现了java.lang.reflect.Member接口,可通过Method对象来执行相应的方法、通过Constructor对象调用对应的构造器创建实例、通过Field对象直接访问或修改对象的成员变量值
创建对象的方式(Constructor对象)
平时的方式:
先加载Person类进入内存
将该类封装成Class对象
根据Class对象,用new操作符创建Person对象
调用构造函数对该对象进行初始化
Person p = new Person();
反射的方式
通过forName()根据指定的类名去查找对应的字节码文件,并加载进入内存
将该字节码文件封装成class对象
直接通过newIntstance()方法完成该类的创建
newInstance()方法调用就是该类中的空参数构造函数完成对象的初始化
方式一:使用classzz对象对应的类的默认构造器
Object object = classzz.newInstance();
方式二:使用classzz对象对应的类的指定的构造器
Constructor constructor = classzz.getConstructor(String.class);
Object object = constructor .newInstance("张三");
方法调用(Method对象)
Person p = new Person();
Class classzz = p.getClass();
Method mtd = classzz.getMethod("setName",String.class);
mtd.invoke(p,"张三");
注:当通过invoke方法来调用对应方法时,要求程序必须有调用该方法的权限。如果需要调用某个对象的private方法,则使用Method.setAccessible(Boolean flag),当值为true时,表示该Method对象在使用时取消访问权限检查
访问成员变量(Field对象)
Person p = new Person();
Class classzz = p.getClass();
Field nameField = classzz.getDeclaredField("name");
nameField.setAccessible(true);
nameField.set(p,"张三");
//nameField.setInt(p,007);
获取成员变量的值:getXXX(Object object);
设置成员变量的值:setXXX(Object object,XXX val);
注:此XXX对应8大基本数据类型,若成员变量的类型为引用数据类型,则直接使用get/set方法