相对而言,反射比内省更容易理解一点。用一句比较白的话来归纳,反射就是让你能够经过名称来获得对象 ( 类,属性,方法 ) 的技术,这种技术比内省机制使用范围更普遍。例如咱们能够经过类名来生成一个类的实例;知道了方法名,就能够调用这个方法;知道了属性名就能够访问这个属性的值。 内省是 Java 语言对 Bean 类属性、事件的一种缺省处理方法。例如类 A 中有属性 name, 那咱们能够经过 getName,setName 来获得其值或者设置新的值。经过 getName/setName 来访问 name 属性,这就是默认的规则。 Java 中提供了一套 API 用来访问某个属性的 getter/setter 方法,经过这些 API 能够使你不须要了解这个规则(但你最好仍是要搞清楚),这些 API 存放于包 java.beans 中。
通常的作法是经过类 Introspector 来获取某个对象的 BeanInfo 信息,而后经过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),经过这个属性描述器就能够获取某个属性对应的 getter/setter 方法,而后咱们就能够经过反射机制来调用这些方法。下面咱们来看一个例子,这个例子把某个对象的全部属性名称和值都打印出来:java
package MyTest; public class bean { private String id = null ; private String name = null ; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } } package MyTest; import java.beans.BeanInfo; import java.beans.EventSetDescriptor; import java.beans.Introspector; import java.beans.MethodDescriptor; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; public class myBeanIntrospector { public myBeanIntrospector() { try { //实例化一个Bean bean beanObj = new bean(); //依据Bean产生一个相关的BeanInfo类 BeanInfo bInfoObject = Introspector.getBeanInfo(beanObj.getClass(),beanObj.getClass().getSuperclass()); //定义一个用于显示的字符串 String output = ""; //开始自省 /* * BeanInfo.getMethodDescriptors() * 用于获取该Bean中的全部容许公开的成员方法,以MethodDescriptor数组的形式返回 * * MethodDescriptor类 * 用于记载一个成员方法的全部信息 * MethodDescriptor.getName() * 得到该方法的方法名字 * MethodDescriptor.getMethod() * 得到该方法的方法对象(Method类) * * Method类 * 记载一个具体的的方法的全部信息 * Method.getParameterTypes() * 得到该方法所用到的全部参数,以Class数组的形式返回 * * Class..getName() * 得到该类型的名字 */ output = "内省成员方法:/n"; MethodDescriptor[] mDescArray = bInfoObject.getMethodDescriptors(); for (int i=0;i<mDescArray.length ;i++ ) { //得到一个成员方法描述器所表明的方法的名字 String methodName = mDescArray[i].getName(); String methodParams = new String(); //得到该方法对象 Method methodObj = mDescArray[i].getMethod(); //经过方法对象得到该方法的全部参数,以Class数组的形式返回 Class[] parameters = methodObj.getParameterTypes(); if (parameters.length>0) { //得到参数的类型的名字 methodParams = parameters[0].getName(); for (int j=1;j<parameters.length ;j++ ) { methodParams = methodParams + "," + parameters[j].getName(); } } output += methodName + "(" + methodParams + ")/n"; } System.out.println(output); /* * BeanInfo.getPropertyDescriptors() * 用于获取该Bean中的全部容许公开的成员属性,以PropertyDescriptor数组的形式返回 * * PropertyDescriptor类 * 用于描述一个成员属性 * * PropertyDescriptor.getName() * 得到该属性的名字 * * PropertyDescriptor.getPropertyType() * 得到该属性的数据类型,以Class的形式给出 * */ output = "内省成员属性:/n"; PropertyDescriptor[] mPropertyArray = bInfoObject.getPropertyDescriptors(); for (int i=0;i<mPropertyArray.length ;i++ ) { String propertyName = mPropertyArray[i].getName(); Class propertyType = mPropertyArray[i].getPropertyType(); output += propertyName + " ( " + propertyType.getName() + " )/n"; } System.out.println(output); /* * BeanInfo.getEventSetDescriptors() * 用于获取该Bean中的全部容许公开的成员事件,以EventSetDescriptor数组的形式返回 * * EventSetDescriptor类 * 用于描述一个成员事件 * * EventSetDescriptor.getName() * 得到该事件的名字 * * EventSetDescriptor.getListenerType() * 得到该事件所依赖的事件监听器,以Class的形式给出 * */ output = "内省绑定事件:/n"; EventSetDescriptor[] mEventArray = bInfoObject.getEventSetDescriptors(); for (int i=0;i<mEventArray.length ;i++ ) { String EventName = mEventArray[i].getName(); Class listenerType = mEventArray[i].getListenerType(); output += EventName + "(" + listenerType.getName() + ")/n"; } System.out.println(output); System.out.println("write by esonghui :"); } catch (Exception e) { System.out.println("异常:" + e); } } public static void main(String[] args) { new myBeanIntrospector(); } }