JAVA的內省機制(introspector)與反射機制(reflection)----轉載http://yangzhibin-java.iteye.com/b...

luxika發表於2011-12-26
相對而言,反射比內省更容易理解一點。用一句比較白的話來概括,反射就是讓你可以通過名稱來得到物件 ( 類,屬性,方法 ) 的技術,這種技術比內省機制使用範圍更廣泛。例如我們可以通過類名來生成一個類的例項;知道了方法名,就可以呼叫這個方法;知道了屬性名就可以訪問這個屬性的值。 內省是 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();
}
}

相關文章