JAVA的内省机制(introspector)与反射机制(reflection)

来源:互联网 发布:英国现存贵族 知乎 编辑:程序博客网 时间:2024/06/07 13:46

相对而言,反射比内省更容易理解一点。用一句比较白的话来概括,反射就是让你可以通过名称来得到对象 ( 类,属性,方法 ) 的技术,这种技术比内省机制使用范围更广泛。例如我们可以通过类名来生成一个类的实例;知道了方法名,就可以调用这个方法;知道了属性名就可以访问这个属性的值。 内省是 Java 语言对 Bean 类属性、事件的一种缺省处理方法。例如类 A 中有属性 name, 那我们可以通过 getName,setName 来得到其值或者设置新的值。通过 getName/setName 来访问 name 属性,这就是默认的规则。 Java 中提供了一套 API 用来访问某个属性的 getter/setter 方法,通过这些 API 可以使你不需要了解这个规则(但你最好还是要搞清楚),这些 API 存放于包 java.beans 中。
一般的做法是通过类 Introspector 来获取某个对象的 BeanInfo 信息,然后通过 BeanInfo 来获取属性的描述器( PropertyDescriptor ),通过这个属性描述器就可以获取某个属性对应的 getter/setter 方法,然后我们就可以通过反射机制来调用这些方法。下面我们来看一个例子,这个例子把某个对象的所有属性名称和值都打印出来:

Java代码 复制代码
  1. package MyTest;   
  2. public class bean {   
  3.         private String id = null ;   
  4.         private String name = null ;   
  5.   
  6.         public String getId() {   
  7.                 return id;   
  8.          }   
  9.         public void setId(String id) {   
  10.                 this.id = id;   
  11.          }   
  12.   
  13.         public String getName() {   
  14.                 return name;   
  15.          }   
  16.         public void setName(String name) {   
  17.                 this.name = name;   
  18.          }   
  19. }   
  20.   
  21. package MyTest;   
  22. import java.beans.BeanInfo;   
  23. import java.beans.EventSetDescriptor;   
  24. import java.beans.Introspector;   
  25. import java.beans.MethodDescriptor;   
  26. import java.beans.PropertyDescriptor;   
  27. import java.lang.reflect.Method;   
  28. public class myBeanIntrospector {   
  29. public myBeanIntrospector()      
  30.    {      
  31.    try     
  32.     {      
  33.     //实例化一个Bean      
  34.      bean beanObj = new bean();      
  35.     //依据Bean产生一个相关的BeanInfo类      
  36.      BeanInfo bInfoObject =       
  37.     Introspector.getBeanInfo(beanObj.getClass(),beanObj.getClass().getSuperclass());      
  38.     //定义一个用于显示的字符串      
  39.      String output = "";      
  40.       
  41.     //开始自省      
  42.         
  43.     /*  
  44.      * BeanInfo.getMethodDescriptors()  
  45.      * 用于获取该Bean中的所有允许公开的成员方法,以MethodDescriptor数组的形式返回  
  46.      *  
  47.      * MethodDescriptor类  
  48.      * 用于记载一个成员方法的所有信息  
  49.      * MethodDescriptor.getName()  
  50.      * 获得该方法的方法名字  
  51.      * MethodDescriptor.getMethod()  
  52.      * 获得该方法的方法对象(Method类)  
  53.      *  
  54.      * Method类  
  55.      * 记载一个具体的的方法的所有信息  
  56.      * Method.getParameterTypes()  
  57.      * 获得该方法所用到的所有参数,以Class数组的形式返回  
  58.      *  
  59.      * Class..getName()  
  60.      * 获得该类型的名字  
  61.      */     
  62.      output = "内省成员方法:/n";      
  63.      MethodDescriptor[] mDescArray = bInfoObject.getMethodDescriptors();      
  64.     for (int i=0;i<mDescArray.length ;i++ )      
  65.      {      
  66.      //获得一个成员方法描述器所代表的方法的名字      
  67.       String methodName = mDescArray[i].getName();      
  68.            
  69.       String methodParams = new String();      
  70.      //获得该方法对象      
  71.       Method methodObj = mDescArray[i].getMethod();      
  72.      //通过方法对象获得该方法的所有参数,以Class数组的形式返回      
  73.       Class[] parameters = methodObj.getParameterTypes();      
  74.      if (parameters.length>0)      
  75.       {      
  76.       //获得参数的类型的名字      
  77.        methodParams = parameters[0].getName();      
  78.       for (int j=1;j<parameters.length ;j++ )      
  79.        {      
  80.         methodParams = methodParams + "," + parameters[j].getName();      
  81.        }      
  82.       }      
  83.       output += methodName + "(" + methodParams + ")/n";      
  84.      }      
  85.      System.out.println(output);      
  86.         
  87.     /*  
  88.      * BeanInfo.getPropertyDescriptors()  
  89.      * 用于获取该Bean中的所有允许公开的成员属性,以PropertyDescriptor数组的形式返回  
  90.      *  
  91.      * PropertyDescriptor类  
  92.      * 用于描述一个成员属性  
  93.      *  
  94.      * PropertyDescriptor.getName()  
  95.      * 获得该属性的名字  
  96.      *  
  97.      * PropertyDescriptor.getPropertyType()  
  98.      * 获得该属性的数据类型,以Class的形式给出  
  99.      *  
  100.      */     
  101.      output = "内省成员属性:/n";      
  102.      PropertyDescriptor[] mPropertyArray = bInfoObject.getPropertyDescriptors();      
  103.     for (int i=0;i<mPropertyArray.length ;i++ )      
  104.      {      
  105.       String propertyName = mPropertyArray[i].getName();      
  106.       Class propertyType = mPropertyArray[i].getPropertyType();      
  107.       output += propertyName + " ( " + propertyType.getName() + " )/n";      
  108.      }      
  109.      System.out.println(output);      
  110.         
  111.       
  112.     /*  
  113.      * BeanInfo.getEventSetDescriptors()  
  114.      * 用于获取该Bean中的所有允许公开的成员事件,以EventSetDescriptor数组的形式返回  
  115.      *  
  116.      * EventSetDescriptor类  
  117.      * 用于描述一个成员事件  
  118.      *  
  119.      * EventSetDescriptor.getName()  
  120.      * 获得该事件的名字  
  121.      *  
  122.      * EventSetDescriptor.getListenerType()  
  123.      * 获得该事件所依赖的事件监听器,以Class的形式给出  
  124.      *  
  125.      */     
  126.      output = "内省绑定事件:/n";      
  127.      EventSetDescriptor[] mEventArray = bInfoObject.getEventSetDescriptors();      
  128.     for (int i=0;i<mEventArray.length ;i++ )      
  129.      {      
  130.       String EventName = mEventArray[i].getName();      
  131.       Class listenerType = mEventArray[i].getListenerType();      
  132.       output += EventName + "(" + listenerType.getName() + ")/n";      
  133.      }      
  134.      System.out.println(output);      
  135.      System.out.println("write by esonghui :");      
  136.         
  137.     }      
  138.    catch (Exception e)      
  139.     {      
  140.      System.out.println("异常:" + e);      
  141.     }      
  142.    }      
  143.   public static void main(String[] args)       
  144.    {      
  145.    new myBeanIntrospector();      
  146.    }      
  147. }