程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 反射:運行期類信息

反射:運行期類信息

編輯:關於JAVA

如果不知道一個對象的准確類型,RTTI會幫助我們調查。但卻有一個限制:類型必須是在編譯期間已知的,否則就不能用RTTI調查它,進而無法展開下一步的工作。換言之,編譯器必須明確知道RTTI要處理的所有類。
從表面看,這似乎並不是一個很大的限制,但假若得到的是一個不在自己程序空間內的對象的句柄,這時又會怎樣呢?事實上,對象的類即使在編譯期間也不可由我們的程序使用。例如,假設我們從磁盤或者網絡獲得一系列字節,而且被告知那些字節代表一個類。由於編譯器在編譯代碼時並不知道那個類的情況,所以怎樣才能順利地使用這個類呢?
在傳統的程序設計環境中,出現這種情況的概率或許很小。但當我們轉移到一個規模更大的編程世界中,卻必須對這個問題加以高度重視。第一個要注意的是基於組件的程序設計。在這種環境下,我們用“快速應用開發”(RAD)模型來構建程序項目。RAD一般是在應用程序構建工具中內建的。這是編制程序的一種可視途徑(在屏幕上以窗體的形式出現)。可將代表不同組件的圖標拖曳到窗體中。隨後,通過設定這些組件的屬性或者值,進行正確的配置。設計期間的配置要求任何組件都是可以“例示”的(即可以自由獲得它們的實例)。這些組件也要揭示出自己的一部分內容,允許程序員讀取和設置各種值。此外,用於控制GUI事件的組件必須揭示出與相應的方法有關的信息,以便RAD環境幫助程序員用自己的代碼覆蓋這些由事件驅動的方法。“反射”提供了一種特殊的機制,可以偵測可用的方法,並產生方法名。通過Java Beans(第13章將詳細介紹),Java 1.1為這種基於組件的程序設計提供了一個基礎結構。
在運行期查詢類信息的另一個原動力是通過網絡創建與執行位於遠程系統上的對象。這就叫作“遠程方法調用”(RMI),它允許Java程序(版本1.1以上)使用由多台機器發布或分布的對象。這種對象的分布可能是由多方面的原因引起的:可能要做一件計算密集型的工作,想對它進行分割,讓處於空閒狀態的其他機器分擔部分工作,從而加快處理進度。某些情況下,可能需要將用於控制特定類型任務(比如多層客戶/服務器架構中的“運作規則”)的代碼放置在一台特殊的機器上,使這台機器成為對那些行動進行描述的一個通用儲藏所。而且可以方便地修改這個場所,使其對系統內的所有方面產生影響(這是一種特別有用的設計思路,因為機器是獨立存在的,所以能輕易修改軟件!)。分布式計算也能更充分地發揮某些專用硬件的作用,它們特別擅長執行一些特定的任務——例如矩陣逆轉——但對常規編程來說卻顯得太誇張或者太昂貴了。
在Java 1.1中,Class類(本章前面已有詳細論述)得到了擴展,可以支持“反射”的概念。針對Field,Method以及Constructor類(每個都實現了Memberinterface——成員接口),它們都新增了一個庫:java.lang.reflect。這些類型的對象都是JVM在運行期創建的,用於代表未知類裡對應的成員。這樣便可用構建器創建新對象,用get()和set()方法讀取和修改與Field對象關聯的字段,以及用invoke()方法調用與Method對象關聯的方法。此外,我們可調用方法getFields(),getMethods(),getConstructors(),分別返回用於表示字段、方法以及構建器的對象數組(在聯機文檔中,還可找到與Class類有關的更多的資料)。因此,匿名對象的類信息可在運行期被完整的揭露出來,而在編譯期間不需要知道任何東西。
大家要認識的很重要的一點是“反射”並沒有什麼神奇的地方。通過“反射”同一個未知類型的對象打交道時,JVM只是簡單地檢查那個對象,並調查它從屬於哪個特定的類(就象以前的RTTI那樣)。但在這之後,在我們做其他任何事情之前,Class對象必須載入。因此,用於那種特定類型的.class文件必須能由JVM調用(要麼在本地機器內,要麼可以通過網絡取得)。所以RTTI和“反射”之間唯一的區別就是對RTTI來說,編譯器會在編譯期打開和檢查.class文件。換句話說,我們可以用“普通”方式調用一個對象的所有方法;但對“反射”來說,.class文件在編譯期間是不可使用的,而是由運行期環境打開和檢查。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved