TIJ筆記(第二版)第12章:執行期型別辨識

來源:互聯網
上載者:User

RTTI的初期想法非常簡單:當有一個指向基礎型別base type的reference時,RTTI機制讓你的一找出其所指的確切型別,不過當拓展到java.lang.reflection的時候,展現了全新的功能.即現在的java中存在兩種形式的rtti:傳統的rtti;reflection機制

為什麼要使用rtti?上面的目的就是原因,比如向下轉型downcasting/強制轉型.
Class類對象以及他的裝載時機。
如何取得某個類/對象的Class對象?
1.Class.forName("Gum");//可能導致執行期異常,比如說找不到Gum類,可以用於編譯時間還未形成的類
2.Gum.class;//這種方式要求編譯時間就裝載Gum類,所以可以執行編譯檢查,一般不會出現找不到Gum類的情況,而且因為不是函數,效能得到最佳化.

我們明確知道Circle也是一個Shape,所以編譯器能夠自動上溯造型,但卻不能保證一個Shape肯定是一個Circle.因此,編譯器不允許自動下溯造型,除非明確指定一次這樣的造型.

轉型之前最好執行類型檢查:(避免執行期異常ClassCastException)
1.傳統轉型:.instanceof if(x instanceof Dog) //這種運算子是使用老式關鍵字,他要求x必須為ref,所以不能用基本類型變數名,而後面的Dog也必須是Class,所以還是不能用基本類型.同時有個缺點就是Dog本身必須是Class名,根本不能用某種變數替換,相比於下面的方法缺少靈活性.
2.操作Class對象:Class.isInstance(obj)//比如Class c=Dog.class;if(c.isInstance(x))....obj也要求是object,輸入基本類型系統會用基本類別wrap之,然後再判斷,注意用基本類型來判斷如int.class.isInstance(x)肯定會返回false,實在想不出你為啥要判斷一個變數是否為基本類型...

 

Java運用Class對象來執行其RTTI機制——即使你所作的只是轉型動作。
Class類型裡面的幾個有用的函數
getInterfaces()  :Class[] //返回一系列介面的class對象。
newInstance() :Object   //虛擬建構函式:我不知道你具體是什麼東西,不過你給我適當的產生一個.若從表面看,Class的newInstance()方法似乎是複製(clone())一個對象的另一種手段。但兩者是有區別的。利用newInstance(),我們可在沒有現成對象供“複製”的情況下建立一個對象。就象上面的程式示範的那樣,當時沒有Toy對象,只有cy——即y的Class對象的一個控制代碼。利用它可以實現“虛擬構建器”。換言之,我們表達:“儘管我不知道你的準確類型是什麼,但請你無論如何都正確地建立自己。”
static Class.forName("Gum"):Class
isInterface():bool    //判斷某個Class對象是否為interface.
getName():string     //得到Class對象所屬的類型的名字。
getSuperclass()
總之,有了某個類的Class對象,他的祖宗十八代都可以查出來。

事實上。RTTI和多態上有重複的功能,先嘗試使用多態,最後才使用RTTI,記住,不要濫用RTTI.

Reflection機制也是通過Class類對象來實現的.

個人感覺他只不過是通過Class類對象暴露了一組共用的借口.我們可以查詢並調用之,而並不用知道某個特定類的全部資訊.事實上他並沒有什麼特別的神奇之處,總感覺有點似曾相識,有點像COM中提供的IUNKNOWN介面,或者IDL語言的作用?

採用傳統RTTI:編譯器在編譯器即開啟並檢查.class檔案,但如果採用Reflection機制,編譯器並不會取用.class檔案.它會由執行期環境加以開啟和檢查.由此我們可以看出reflection的使用場合:JavaBeans,RMI,object serialization.或者無法得知某.class檔案提供的介面時.基本上我們編成的過程中不會直接用到Reflection.

即reflection的意思是我們用Class.forName()尋找的class資訊編譯期間完全不可得,但是在啟動並執行時候可以得到,我們一樣可以查他的祖宗十八代。可以在運行時做任何編譯是想做的事,比如我可以Class.forName()載入執行期才可見的某class,然後可以用class.newInstance(Constructor)來調用該類的某個建構函式構造一個對象,然後用method.invoke(args)來調用這個對象的某個方法。注意reflection機制拓展了Class類來支援更強的非基本rtti功能。

傳統RTTI和“反射”之間唯一的區別就是對RTTI來說,編譯器會在編譯期開啟和檢查.class檔案。換句話說,我們可以用“普通”方式調用一個對象的所有方法;但對“反射”來說,.class檔案在編譯期間是不可使用的,而是由運行期環境開啟和檢查。

想象一下javabean的實現吧,但是RMI,object serialization裡如何應用reflection倒是需要仔細研究。

 

查一下java.lang.reflection包,發現包含以下內容:
介面 Member
類 Array
Constructor
Field
Method
Modifier
異常 InvocationTargetException

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.