通常,在开发过程中,为了提高程序的拓展性,通常会定义用于拓展的接口,每次扩展功能都需要修改代码传递一个新创建的对象,能不能不修改代码就完成这个动作?
不用new来完成,而是只获取class文件,在内部完成创建对象的动作。
反射机制概念
JAVA反射机制就是在运行状态中,对于任意一个类(class文件),都能够知道这个类的所有属性和方法。对于任意一个对象,都能够调用它的任意一个方法和属性,这种动态获取的信息以及动态调用对象的方法的功能成为java语言的反射机制。
动态获取类中信息,就是java反射。可以理解为对类的解剖。要想对字节码文件进行解剖,必须要有字节码文件对象。
这就用到了Class类。
反射机制的应用
反射机制的两个关键的组成:一是要有用于拓展的接口,二是要有配置文件,用于记录拓展功能的类名。
创建实现了拓展功能的接口,在配置文件中设置其参数,在应用程序中添加读取配置文件的函数,即可实现实时的功能拓展,而不必修改程序的代码。
Class类的使用
1,获取字节码文件
获取字节码文件使用Class类的forName()方法
String className = "reflect.Person";
Class clazz = Class.forName(className);
2,创建类的对象
获取了字节码文件后,就可以创建类的对象
Class类的newInstance()方法可以调用该类的空参数构造函数
Person p = (Person)clazz.newInstance();
当要获取指定名称对应类所体现的对象时,若该对象初始化不使用空参数构造方法该怎么办呢?
既然是通过指定的构造函数进行对象的初始化,那么应该先获取该构造方法,通过字节码文件对象即可完成,该方法是:getConstructor(paramterTyps)
//获取到了指定的构造函数对象
Constructor constructor = clazz.getConstructor(String.class,int.class);
//通过该构造器对象的newInstance方法进行对象的初始化
constructor.newInstance("小强",30);
3,获取类的属性
使用getField(String name)和getDeclaredField(String name)方法可以获取类的属性对象(Field)
注意,若要使用该类实例的属性,需要先明确该属性所属对象,即必须先创建对象,并在设置属性时传入该对象
Class clazz = Class.forName("reflect.Person");
//Field field = clazz.getField("age");//只能获取公有的,可以获取父类的
Field field = clazz.getDeclaredField("age");//只获取本类,但包含私有
//对私有字段的访问取消权限检查。暴力访问
field.setAccessible(true);
Object obj = clazz.newInstance();
field.set(obj, 89);
Object o = field.get(obj);
System.out.println(o);
4,获取类的方法
和获取属性相似,使用getMethod(String name,parameterTypes)和getDeclaredMethod(String name,parameterTypes)方法可以获取类的属性对象(Method)
获取指定Class中的所有公共方法
Class clazz = Class.forName("reflect.Person");
//Method[] methods = clazz.getMethods();//获取本类公有方法
Method[] methods = clazz.getDeclaredMethods();//只获取本类中所有方法,包含私有
for(Method method:methods){
System.out.println(method);
}
获取一个无参数方法
Class clazz = Class.forName("reflect.Person");
Method method = clazz.getMethod("show", null);//获取空参数一般方法
Constructor constructor = clazz.getConstructor(String.class,int.class);
Object obj = constructor.newInstance("小明",20);
method.invoke(obj, null);
获取一个有参数方法
Class clazz = Class.forName("reflect.Person");
Method method = clazz.getMethod("paramMethod", String.class,int.class);//获取空参数一般方法
Object obj = clazz.newInstance();
method.invoke(obj, "小强",22);