Java反射机制和内省机制
A.反射机制:
反射在项目里的应用:Java的反射机制主要运用在一些框架里,可以通过反射机制动态的获得对象和调用方法,在项目里 action里运用了反射机制来执行特定的方法。如果不运用反射机制,那么在该项目里,一个动作类就必须定义一个action,(这是因为当HTTPServletRequest请求到来时,会自动执行动作类里的execute方法)那必然会使action动作类,非常的繁杂,但其实很多动作是一个模块里的操作,完全可以放到一个动作类里,然后通过反射机制动态获得动作类里的指定方法。这样做的好处非常明显,大大简化了项目代码结构,让整个项目更具模块性。
当然,在很多开源框架上,Java反射机制也运用的很广,在框架上的具体运用还不是很清楚,有待以后研究。
在这篇文章里,我将介绍一些反射的基本语法和操作:并结合公司的具体运用来进行介绍。
Java反射机制可以实现以下功能:
1. 在运行的时候获得任意对象的类:这个可能比较难以理解,但只需先记住这点,然后慢慢看代码和解说,多看几次就会有说领悟。
2. 根据需要,在运行时可构造任意一个类的对象。说道这里我觉得可以说有三个东西帮程序构造对象;第一个是大家最喜欢也是最熟悉的通过类本身创建一个对象。第二个是通过反射得到这个对象的Class(我觉得也可以这样说,获得这个对象对应的Class类的一个对象),然后通过Class调用newInstance()来构造这个对象所代表的类的一个新对象,必须注意的是,Class的newInstance()方法是不带参数的。如果要构造带指定参数的对象,则要用第三种方法。第三种方法也必须先获得这个对象对应Class类的一个对象,然后通过这个Class的对象调用getConstructor(Class[] cl)得到一个Constructor的对象,最后Constructor的对象再调用newInstance(Object[] objs)方法来构造带参数的对象。
3. 在运行时获得任意对象的方法,包括私有的方法和受保护的方法,但感觉即使能获得也没啥用处?如果有高人知道具体作用请告知。
4. 可在运行时获得任意对象的属性。包括私有属性
在上述介绍中提到一个Class类,该类和绝大多数类一样继承了Object类,但它同时也是一个非常个数的类。这个类的实体主要表示的是一个正在运行的对象的class和interface,这个比较好理解,但它还表示enum,array,primitive,Java Types等。Class类是在ClassLoader的defineClass()被调用时创建一个Class对象。它是一切反射机制的基础,可以这样说:没有Class就没有反射机制,java功能也就大打折扣。
通过类名构造对象:
如果是非基本类型,可通过如下几种方式获得Class类的对象
a. 对象.getClass()
b. 类名.Class
c. Class.forName(String className):注意这里传一个类名做参数
基本类型(包括封装类型):
a. Integer.Class
b. Integer.TYPE
代码如下:
无参:
Class cl=Class.forName(“类名”);
Object obj=cl.newInstance();
有参:
public Object getObject(String className, Object[] objs) throws Exception {
Class class=Class.forName(className);
Class[] classes=new Class[objs.length];
for(int i=0;i<objs.length;i++) {
classes[i]=objs[i].getClass();
}
Constructor con=class.getConstructor(classes);
Object obj=con.newInstance(objs);
return obj;
}
获取(或执行)某对象的方法:
public void invoke(Object obj, String methodName, Object[] objs) throws Exception {
Class class=obj.getClass();
Class[] classes=new Class[objs.length];
for(int i=0;i<objs.length;i++) {
classes[i]=objs[i].getClass();
}
Method method=class.getMethod(methodName, classes);
method.invoke(obj,objs);
//注意如果是要执行静态方法,则上面一行不需传obj 直接method.invoke(null,objs);
}
获取某对象的属性:
public Object getField(Object obj, String fieldName) throws Exception {
Class class=obj.getClass();
Field field=class.getField(fieldname);//或得到所有的共有属性getFields();
Object obj=field.get(obj);//获得指定对象该字段的值,以对象类型返回
return obj;
//如果是静态属性则只需field.get(class);
}
以上方法都不能获得超类的方法和属性,但可通过该Class对象获得超类的Class对象,通过获得的超类Class对象再获得方法和属性。可通过如下递归来完成:
public void getField(Class class){
Class cls=class.getSuperclass();
if(!cls.equals(Object.class)){
Field[] fields = cls.getFields();
getField(cls);
}
}
B.内省机制:
本人对内省机制其实只大概知道怎么用,但它具体有什么牛的地方我还没体会到,可能是我做的项目太少的缘故吧;说句废话:实践是检验真理的唯一标准。
以下是本人摘自网上资料后整理的,希望对各位观众能有所帮助:
内省是Java对Bean类的属性和事件的一种处理机制,也就是给定一个JavaBean对象就可以调用它们所有的get/set方法。
Java提供一个API来访问属性的get/set方法,通过Introspector来的getBeanInfo(Class<?> startClass, Class<?> endClass)来获得一个对象的BeanInfo信息(它是一个接口),注意其中的2个参数的意义:第一个参数表示需要内省的bean对象所代表的Class的对象;第二个参数表示结束内省的类的Class的对象,一般来说,第二个参数是其直接父类的Class的对象。然后通过这个BeanInfo的getPropertyDescriptors()获取每个属性的属性描述器(PropertyDescriptor)的一个数组,该属性描述器表示属性的名字,属性的类型和所有的读写方法。最后通过该属性描述器就可以获得属性的get/set方法对其进行操作。
下面我将展示内省机制的基本运用代码:
private String name;
private String[] childName;
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
public String[] getChildName() {
return childName;
}
public void setChildName(String[] childName) {
this.childName=childName;
}
}
public class TestIntrospector {
public static void main(String[] args) {
TestBean bean=new TestBean();
BeanInfo info=null;
try {
info = Introspector.getBeanInfo(bean.getClass());
} catch (IntrospectionException e) {
e.printStackTrace();
}
PropertyDescriptor[] des=info.getPropertyDescriptors();
for(PropertyDescriptor pro:des) {
String str=pro.getName();//获取属性名
Class type=pro.getPropertyType();//得到属性的类型
if(type.isArray()) { //判断是否是数组
if(str.equals("childName")) {
//getComponentType()获得数组类型的类型,如果不是数组,返回null
if(type.getComponentType().equals(String.class)) {
Method method=pro.getWriteMethod();
new Object[]{new String[]{"bao","ning"}});
}
}
} else if("name".equals(pro.getName())){
Method method=pro.getWriteMethod();
method.invoke(bean,new Object[]{"liu"});
}
}
}
}
以上代码是内省机制最基本的运用,集体框架上的运用还不的而知,希望广大广众不吝赐教。