不少朋友在深刻的接觸 JAVA 語言後就會發現這樣兩個詞:反射 (Reflection) 和內省 (Introspector) ,常常搞不清楚這究竟是怎麼回事,在什麼場合下應用以及如何使用?今天把這兩者放在一塊兒介紹,由於它們兩者是相輔相成的。html
反射java
<?xml:namespace prefix = o /?>
相對而言,反射比內省更容易理解一點。用一句比較白的話來歸納,反射就是讓你能夠經過名稱來獲得對象 ( 類,屬性,方法 ) 的技術。例如咱們能夠經過類名來生成一個類的實例;知道了方法名,就能夠調用這個方法;知道了屬性名就能夠訪問這個屬性的值。數據庫
仍是寫兩個例子讓你們更直觀的瞭解反射的使用方法:框架
// 經過類名來構造一個類的實例
Class cls_str = Class.forName( "java.lang.String" );
// 上面這句很眼熟,由於使用過 JDBC 訪問數據庫的人都用過 J
Object str = cls_str.newInstance();
// 至關於 String str = new String();
this
// 經過方法名來調用一個方法
String methodName = "length" ;
Method m = cls_str.getMethod(methodName, null );
System.out.println( "length is " + m.invoke(str, null ));
// 至關於 System.out.println(str.length());
spa
上面的兩個例子是比較經常使用方法。看到上面的例子就有人要發問了:爲何要這麼麻煩呢?原本一條語句就完成的事情幹嘛要整這麼複雜?沒錯,在上面的例子中確實沒有必要這麼麻煩。不過你想像這樣一個應用程序,它支持動態的功能擴展,也就是說程序不從新啓動可是能夠自動加載新的功能,這個功能使用一個具體類來表示。首先咱們必須爲這些功能定義一個接口類,而後咱們要求全部擴展的功能類必須實現我指定的接口,這個規定了應用程序和可擴展功能之間的接口規則,可是怎麼動態加載呢?咱們必須讓應用程序知道要擴展的功能類的類名,好比是 test.Func1 ,當咱們把這個類名 ( 字符串 ) 告訴應用程序後,它就可使用咱們第一個例子的方法來加載並啓用新的功能。這就是類的反射,請問你有別的選擇嗎?.net
關於方法的反射建議你們看個人另一篇文章《 利用 Turbine 的事件映射來擴展 Struts 的功能 》,地址是: http://www.javayou.com/article/CSDN/extend_struts.html 。這篇文章詳細介紹了若是經過反射來擴展 Struts 框架的功能。設計
內省orm
內省是 Java 語言對 Bean 類屬性、事件的一種缺省處理方法。例如類 A 中有屬性 name, 那咱們能夠經過 getName,setName 來獲得其值或者設置新的值。經過 getName/setName 來訪問 name 屬性,這就是默認的規則。 Java 中提供了一套 API 用來訪問某個屬性的 getter/setter 方法,經過這些 API 可使你不須要了解這個規則(但你最好仍是要搞清楚),這些 API 存放於包 java.beans 中。xml
通常的作法是經過類 Introspector 來獲取某個對象的 BeanInfo 信息,而後經過 BeanInfo 來獲取屬性的描述器( PropertyDescriptor ),經過這個屬性描述器就能夠獲取某個屬性對應的 getter/setter 方法,而後咱們就能夠經過反射機制來調用這些方法。下面咱們來看一個例子,這個例子把某個對象的全部屬性名稱和值都打印出來:
/*
* Created on 2004-6-29
*/
package demo;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
/**
* 內省演示例子
* @author liudong
*/
public class IntrospectorDemo {
String name;
public static void main(String[] args) throws Exception{
IntrospectorDemo demo = new IntrospectorDemo();
demo.setName( "Winter Lau" );
// 若是不想把父類的屬性也列出來的話,
// 那 getBeanInfo 的第二個參數填寫父類的信息
BeanInfo bi = Introspector.getBeanInfo(demo.getClass(), Object. class );
PropertyDescriptor[] props = bi.getPropertyDescriptors();
for ( int i=0;i
System.out.println(props[i].getName()+ "=" +
props[i].getReadMethod().invoke(demo, null ));
}
}
public String getName() {
return name;
}
public void setName(String name) {
this .name = name;
}
}
Web 開發框架 Struts 中的 FormBean 就是經過內省機制來將表單中的數據映射到類的屬性上,所以要求 FormBean 的每一個屬性要有 getter/setter 方法。但也並不老是這樣,什麼意思呢?就是說對一個 Bean 類來說,我能夠沒有屬性,可是隻要有 getter/setter 方法中的其中一個,那麼 Java 的內省機制就會認爲存在一個屬性,好比類中有方法 setMobile ,那麼就認爲存在一個 mobile 的屬性,這樣能夠方便咱們把 Bean 類經過一個接口來定義而不用去關心具體實現,不用去關心 Bean 中數據的存儲。好比咱們能夠把全部的 getter/setter 方法放到接口裏定義,可是真正數據的存取則是在具體類中去實現,這樣可提升系統的擴展性。
總結
將 Java 的反射以及內省應用到程序設計中去能夠大大的提供程序的智能化和可擴展性。有不少項目都是採起這兩種技術來實現其核心功能,例如咱們前面提到的 Struts ,還有用於處理 XML 文件的 Digester 項目,其實應該說幾乎全部的項目都或多或少的採用這兩種技術。在實際應用過程當中兩者要相互結合方能發揮真正的智能化以及高度可擴展性。
此文轉載自 :想飛的魚 2007-03-05 17:40