標籤:
轉載請註明出處:jiq?欽‘s technical Blog
1 Class檔案:
class檔案全名稱為Javaclass檔案,主要在平台無關性和網路移動性方面使Java更適合網路。它在平台無關性方面的任務是:為Java程式提供獨立於底層主機平台的二進位形式的服務。
每一個類都有一個Class類型的對象,每當一個類被編譯,就會產生一個Class對象(儲存在同名的.class檔案中);
2 Class檔案載入時機:
運行時按需載入。
與普通程式不同的是,Java程式(class檔案)並不是本地的可執行程式。當運行Java程式時,首先運行JVM,然後再根據需要在運行時把Java class載入到JVM裡頭運行,負責載入Java class的這部分就叫做Class Loader。
三種情況會觸發Class Loader動態載入class對象到JVM:
(1)第一次靜態方法被調用;
(2)第一次被new執行個體化;
(3)包含靜態代碼塊;
一旦某個類的Class對象被載入記憶體,他就被用來建立這個類所有對象;
3 RTTI三種表現形式:
Java是藉助Class對象來實現RTTI機制的,java中RTTI有三種表現形式:
1).傳統的類型轉化。
如Base類是Subclass類基類。
Base base = newSubclass();
Subclass sub=(Subclass)base;//由RTTI確定類型轉化正確性
2).通過代表對象的類型的Class對象可以擷取運行時所需的資訊。
3).關鍵字“instanceof”判斷物件類型。
如:boolean yesOrNot = (baseinstanceof Subclass);
若base是Subclass類的執行個體,yesOrNot就為true。
4 RTTI限制:
書上流傳一句話:RTTI和反射的區別是,對RTTI來說,編譯器在編譯時間開啟和檢查.class檔案,對於反射機制來說,.class檔案在編譯時間是不可擷取的,所以是在運行時開啟和檢查.class檔案。
這個要怎麼理解呢???
RTTI是在編譯期間就已經知道了所有要處理的類型,但是有時運行時需要解析一個對象,比如你在磁碟檔案或者網路中擷取了一串位元組,並被告知這些位元組代表某一個類,但是很不幸代碼中沒有任何相關操作觸發對應的class檔案被載入到JVM,這就是所謂的運行時開啟和檢查.class檔案。
5反射機制
這時就需要通過顯式告知JVM載入哪個class檔案,以擷取對應類型資訊。
取得Class對象(若還未載入則先載入)的引用有兩種方式:
(1)方法Class.forName("className")
(2) .class 類字面常量。
兩者區別在於後者會將類的初始化(static地區的執行)延遲到後面對該類的靜態域引用的時候;
Class<?>classObject = Class.forName("className");
Method[]methods = classObject.getMethods();
Constructor[]ctors = classObject.getConstructors();
由此可見,Class類是RTTI的基礎,而Class類與java.lang.reflect類庫一起對反射概念進行了支援。
6反射的不安全性
即使你是面向介面編程,只提供出“希望可見的部分”給用戶端,但是你仍然無法避免你的不可見的私人的,或者不是私人的一切方法被用戶端使用的命運,你無法阻止這樣的耦合。用戶端通過反編譯+反射機制就可以突破你的任何防線。但是如果有人這麼幹了,那這是他們的責任。
7 Spring中的依賴注入
Spring中的依賴注入就是依靠反射機制才得以實現的。
首先Spring會讀取器設定檔中配置的那些bean,然後擷取其要注入的對象的類名,這樣就可以根據:
Classs bean = Class.forName("className");
Objectoo = bean.newInstance();
這樣就建立好了一個待注入的類的對象。
我們利用反射機制一樣可以擷取注入目標Action的所有方法,包括其setXXX方法,因此我們接下來便可以通過調用
Method#invoke(方法名稱,參數)這個方法來將建立好的對象注入進去了。
8 利用反射機制建立執行個體:
(1) 建立普通執行個體:
(2) 建立一維數組:
(3) 建立二維數組:
Java基礎:RTTI與反射