这里想学一下反射和内省。
内省使用的是反射的技术,所以反射是基础。
反射的主要用途是用于框架之中,通过反射技术就可以创建通过配置文件传入的类的对象了。
我使用反射一种场景就是首先定义一个接口或者虚基类,要求在配置文件中传入的实现了接口或继承了基类的类文件名及参数。然后就可以通过反射创建这些对象。而我们只需要使用接口或虚基类去接收对象,这样,我们就可以在不需要知道对象具体的情况下正确的使用这个对象。这样,程序的扩展性大大增强,而且通过设置配置文件,可以统一的管理其内部的资源。
要学反射,就得首先学Class,java认为万物皆对象,而这个Class就是这个对象的特征,通过这个特征,虚拟机就能正确的识别这个对象。即使是基础类型也是有自己的Class文件的。反射就是通过调用Class的方法,来统一化的识别类。
反射的主要,,目的是获得构造函数,成员字段,方法。而构造函数,成员字段,方法又都是具体的一个类,通过调用其对应的方法,就可以完全的操纵这个类了。
首先是来说说怎么获取类文件。
对于对象来说,通过一个对象.getClass()方法可以获得。对于类来说直接使用类名.class就可以获得。返回的是一个Class文件。
还有一种方式是通过Class.fromName(完整的类名“)来获得,这也是通过配置文件获取Class的方法。
获取构造函数。
Constructor
Constructor cons = clazz.getConstructor(int.class,
String.class, int.class);
通过调用 cons.newInstance(参数),可以创建一个新的实例对象。
获取成员字段。
public Field getField(String name), 根据字段名来获取字段对象。
调用Field的方法就可以读取,修改指定对象的该字段的值,还可查看这个字段的属性,如类型等。
get(Object obj)(获取指定对象的该对象的值),set(Object obj,Object value)(设置指定对象的该字段的值)。getType()(获取字段的类型。)
获取方法:
Method getMethod(String name, Class>... parameterTypes) 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。
同样的,调用方法对象的Object invoke(Object obj, Object... args)方法就可以使用这个方法了。
以上三种当在方法后面加上s后,就不需要加上参数来识别了,表示返回所有的构造函数,字段,方法。
但是以上的都是查找的public的构造函数,字段,方法,可以在get后面加上Declared,来表示查找所有声明的构造函数,字段,方法。可以通过调用其返回值的setAccessible(boolean)来改变其权限,就可以自由的读写了。这也被称为暴力反射。
内省(Introspector)是Java语言对Bean类属性、事件的一种缺省处理方法。
属性,当类的方法里面有getXXX或setXXX方法 这样xxx就被称为类的属性,相同xxx的get,set只称为一个属性。
我的想法是:get,set 一般而言,后面接的都是一个名词,而这个名词时跟这个对象特征息息相关的,外部读取或者设置这些属性,来修改对象特征或者获取对象特征。
Introspector 是封装了一系列的与bean相关的静态方法。
public static BeanInfo getBeanInfo(Class> beanClass)//这个方法可以返回一个BeanInfo对象,它包含了bean 的属性、事件等显式信息。
通过调用BeanInfo对象的各种方法,就可以获取其bean属性对象,方法对象,事件对象。
PropertyDescriptor对应于属性描述器。MethodDescriptor 方法描述器 -ParameterDescriptor 方法的参数描述器
也可以直接调用以上的带class的构造函数来直接创建类对应的描述器对象。
BeanUtils工具包是由Apache公司所开发。是以另外一种操作bean的属性的方法。属于第三方jar包,但比javabean更强大。beanUtils的使用需要导入两个jar包,一个beanUtils包,一个Logic4j的jar包。
BeanUtils.setProperty(对象,bean属性,新的值);//这是使用BeanUtils快速设置属性的方法。
假如bean属性是8种基本类型,则新的值可以自动转换成对应的基本类型。
如果bean属性是复杂类型,则可以通过在beanUutils注册类型转换器,以后就可以自动进行对应的类型转换。
ConvertUtils.register(new DateLocaleConverter(), Date.class);//第一个参数是新的转换器,要求实现Converter接口。第二个参数为属性的类型。
复写public Object convert(Class type, Object value) //这个方法,在遇到属性为Data时,会自动调用此方法,将传入的值给参数,最后将返回值赋予属性。