TIJ閱讀筆記(第十章)

來源:互聯網
上載者:User
筆記
10:檢測類型  運行時類型識別(run-time type identification,縮寫為RTTI)。

為什麼會需要RTTI  collection是一種工具,它只有一種用途,就是要為你保管其它對象。因此出於通用性的考慮,這些collection應該能持有任何東西。所以它們持有Object。    Class對象    想要知道JAVA的RTTI是如何工作的,你就必須首Crowdsourced Security Testing道程式啟動並執行時候,類型資訊是怎樣表示的。這是由一種特殊的,儲存類的資訊的,叫做“Class對象(Class object)”的對象來完成。實際上類的“常規”對象是由Class對象建立的。    程式裡的每個類都要有一個Class對象。也就是說,每次你撰寫並且編譯了一個新的類的時候,你就建立了一個新的Class對象(而且可以這麼說,這個對象會儲存在同名的.class檔案裡)。程式運行時,當你需要建立一個那種類的對象的時候,JVM會檢查它是否裝載了那個Class對象。如果沒有,JVM就會去找那個.class檔案,然後裝載。由此也可知道,Java程式在啟動的時候並沒有完全裝載,這點同許多傳統語言是不一樣的。        Class.forName("一個類的名字");    這是一個Class的static方法(所有的Class對象所共有的)。Class對象同其它對象一樣,也可以用reference來操控(這是裝載器要乾的),而要想擷取其reference, forName()就是一個辦法。它要一個表示這個類的名字的String作參數(一定要注意拼字喝大小寫!)。這個方法會返回Class的reference,還有一個副作用,看看這個String所說的那個類裝載了沒有,要是還沒有那就馬上裝載。如果Class.forName()沒有找到它要裝載的類,就會拋出一個ClassNotFoundException。        Class常數    Java還提供了一種擷取Class對象的reference的方法:“class常數(class literal)”。      類的名字.class;    這種寫法不但更簡單,而且也更安全,因為它是在編譯時間做檢查的。此外由於沒有方法調用,它的執行效率也更高一些。        Class常數不但能用於普通類,也可以用於介面,數組和primitive類型。此外,每種primitive的wrapper類還有一個標準的,名為TYPE的資料成員。這個TYPE能返回“與這種primitive相關聯的wrapper類”的Class對象的reference,就像這樣:             ... 等同於 ...    boolean.class    Boolean.TYPE    char.class       Character.TYPE    byte.class       Byte.TYPE    short.class      Short.TYPE    int.class        Integer.TYPE    long.class       Long.TYPE    float.class      Float.TYPE    double.class     Double.TYPE    void.class       Void.TYPE        我喜歡盡量使用“.class”,因為這種寫法與普通類的保持一致。    轉換之前先作檢查    到目前為止,你看到的RTTI的形式有:      1。經典的類型轉換:如“(Shape)”,這種轉換要經過RTTI的檢查。要是做了錯誤的轉換,它就會拋出ClassCastException。      2.代表物件類型的Class對象。你可以在啟動並執行時候查詢Class對象,以此來擷取所需的資訊。        如果不進行明確的類型轉換的話,編譯器時不會讓你把對象賦給衍生類別的reference的。    Java裡面還有第三種RTTI的形式。這就是instanceof關鍵詞,它會告訴你對象是不是某個類的執行個體。它返回的是一個boolean值。    使用類常數    動態instanceof    isInstance()能完全替代instanceof。    instanceof vs. Class的相等性

RTTI的文法    Class.getInterfaces()方法會返回一個Class對象的數組。數組中的對象分別表示它所實現的介面。  如果你手上有一個Class對象,你還能用getSuperclass()問出它最近的那個父類。當然,這會返回一個Class的reference,於是你可以接著問,程式啟動並執行時候,你能以此發現對象的完整的關係。  Class的newInstance()方法就像是另一種clone()對象的方法。但是,你卻可以用newInstance()憑空建立出一個新的對象。  printInfo()方法,它拿一個Class對象的reference作參數,用getName()提取類的名字,用isInterface()判斷它是不是介面。這樣,你就能僅憑Class對象就找出所有你想知道的這個對象的資訊了。

Reflection:運行時的類資訊  Java以JavaBeans的形式提供了基於組件的編程的支援。  通過網路在遠程機器上建立對象並運行程式。這被成為“遠程方法調用(Remote Method Invocation縮寫是RMI)”。它能讓一個Java程式將對象分布到很多機器上。  除了Class類,還有一個類庫,java.lang.reflect也支援reflection。這個類庫裡面有Field,Method,和Constructor類(它們都實現了Member介面)運行時,JVM會建立一些這種類的對象來代表未知類的各個成員。然後,你就能用Constructor來建立新的對象,用get()和set()來讀取和修改與Field隊形愛女嘎相關聯的成員資料,用invoke()方法調用與Method對象相關聯的方法了。此外,你還能用getFields(),getMethods(),getConstructors()之類的方法,擷取表示成員資料,方法或建構函式的對象數組。由此,即便編譯時間什麼資訊都得不到,你也有辦法能在運行時問出匿名對象的全部類型資訊了。  有一點很重要,reflection不是什麼妖術。當你用reflection與未知類的對象打交道的時候,JVM(會和普通的RTTI一樣)先看看這個對象是屬於那個具體類型的,但是此後,它還是得先裝載Class對象才能工作。也就是,不管是從本地還是從網路,反正JVM必須拿到那個.class檔案。所以RTTI同reflection的真正區別在於,RTTI是在編譯時間讓編譯器開啟並且檢查.class檔案。換句話說,你是在通過“正常”途徑調用對象的方法。而對reflection來說,編譯時間是得不到.class檔案的;所以它是在運行時開啟並檢查那個檔案。    一個提取類的方法的程式    一般來說,你不太會直接使用reflection;Java之所以要有這種功能是要用它來支援一些憋的特性,比如對象的序列化和JavaBeans。不過在有些情況下,能動態提取類的資訊還是很有用的。    Class的getMethods()和getConstructors()方法分別會返回一個Method和一個Constructor數組。這兩個類又包括一些“能把它們所代表的方法的名字,參數,傳回值全部拆解開來”的方法。不過你也可以像這裡所作的,只用toString()去擷取一個包括這個方法的全部特徵簽名的String。剩下的代碼就是用來抽取命令列資訊,以及判斷方法特徵是否與你輸入的字串相匹配(用indexOf()),並且把匹配的方法列出來的。

總結:  RTTI能讓你用一個匿名的基類reference來擷取對象的確切類型的資訊。在不懂多台方法調用的時候,這麼作是理所當然的,因此新手們會自然而然的想到它,於是就用錯了地方,對很多從面向過程的程式設計語言轉過來的人來說,剛開始的時候,它們還不習慣扔掉switch語句。於是當他們用RTTI來編程的時候,就會錯過多態性所帶來的編程和代碼維護方面的好處。Java的本義是讓你在程式裡面全程使用多態性,知識在萬不得已的情況下才使用RTTI。  但是要想正確地使用多台方法調用,你就必須要能控制基類的定義,因為當你擴充程式的時候,可能會發現基類裡面沒有你想要的方法。如果這個基類是來自類庫的,或是由別人控制的,那麼RTTI就成解決方案了:你可以繼承一個新的類,然後加上你自己的方法。在程式的其他地方,你可以檢測出這個類型,調用那些特殊的方法。這樣做不會破壞多態性,也不影響程式的擴充性,因為加一個新的類型不會要你去到處修改switch語句。但是,如果是在程式的主體部分加入要使用新特性的嗲馬的話,你就必須使用RTTI來檢查對象的確切類型了。  RTTI還會被用來解決效率問題。假設你寫了一個很好的多台程式,但是啟動並執行時候發現,有個對象反映奇慢。於是,你就可以用RTTI把則個對象撿出來,然後專門針對它的問題寫代碼以提高程式的運行效率,不過編程的時候切忌去過早有話代碼。這是一個很有誘惑的陷阱。最好還是先讓程式跑起來,然後再判斷一下它跑得是不是夠快了。只有覺得它還不夠快,你才應該去著手解決效率問題--用profiler。


相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

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

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