杜叔強(qiáng)
摘 要:反射是Java語(yǔ)言中的一種重要的編程機(jī)制;總結(jié)了Java語(yǔ)言中反射的原理,以及反射相關(guān)類的獲取方式,并總結(jié)了反射機(jī)制的幾點(diǎn)應(yīng)用。
關(guān)鍵詞:反射機(jī)制 Class Constructor Field Method
1反射的概念
Java反射是Java被視為動(dòng)態(tài)(或準(zhǔn)動(dòng)態(tài))語(yǔ)言的一個(gè)關(guān)鍵性質(zhì)。這個(gè)機(jī)制允許程序在運(yùn)行時(shí)通過(guò)反射API取得任何一個(gè)已知名稱的類的內(nèi)部信息,包括其訪問(wèn)修飾符、父類、實(shí)現(xiàn)的接口,也包括屬性和方法的所有信息,并可在運(yùn)行時(shí)改變屬性值或進(jìn)行方法調(diào)用。Java反射機(jī)制容許程序在運(yùn)行時(shí)加載、探知、使用編譯期間完全未知的類。也就是說(shuō),Java可以加載一個(gè)運(yùn)行時(shí)才得知名稱的類,并且獲得其完整結(jié)構(gòu)信息,這種動(dòng)態(tài)獲取信息以及動(dòng)態(tài)調(diào)用對(duì)象的成員的功能稱為java語(yǔ)言的反射機(jī)制[1]。
2反射的原理
Java反射機(jī)制的實(shí)現(xiàn)要借助于4個(gè)類:Class,Constructor,F(xiàn)ield,Method;其中Class代表的是類對(duì)象,Constructor是類的構(gòu)造器對(duì)象,F(xiàn)ield是類的屬性對(duì)象,Method是類的方法對(duì)象,通過(guò)這四個(gè)對(duì)象我們可以粗略的看到一個(gè)類的各個(gè)組成部分。其中最核心的就是Class類,它是實(shí)現(xiàn)反射的基礎(chǔ)。Class類的實(shí)例就是某個(gè)類的描述信息。Class類的實(shí)例表示正在運(yùn)行的Java應(yīng)用程序中的類和接口。
Class沒(méi)有公共構(gòu)造方法。Class對(duì)象是在加載類時(shí)由Java虛擬機(jī)以及通過(guò)調(diào)用類加載器中的defineClass方法自動(dòng)構(gòu)造的。JVM在程序第一次主動(dòng)使用某個(gè)類的時(shí)候,才會(huì)去加載該類。也就是說(shuō),JVM并不是在一開(kāi)始就把一個(gè)程序所有的類都加載到內(nèi)存中,而是到用的時(shí)候才把它加載進(jìn)來(lái),而且只加載一次。當(dāng)JVM加載某個(gè)類時(shí),會(huì)到本地磁盤(pán)去找到這個(gè)類的字節(jié)碼文件,然后將這個(gè)字節(jié)碼文件加載到JVM內(nèi)存中,并且在內(nèi)存堆區(qū)創(chuàng)建這個(gè)類的Class對(duì)象。注意這個(gè)不是new出來(lái)的對(duì)象,而是類的類型描述對(duì)象,每個(gè)類只有一個(gè)Class對(duì)象,作為類的數(shù)據(jù)結(jié)構(gòu)的接口。JVM創(chuàng)建對(duì)象前,會(huì)先檢查類是否加載,尋找類對(duì)應(yīng)的Class對(duì)象,若類已加載好,則為待創(chuàng)建對(duì)象分配內(nèi)存。有了類型信息描述對(duì)象Class對(duì)象,就可以獲取類的屬性,方法等信息。
3 Class對(duì)象的獲取
有三種方式可以獲取Class對(duì)象[2]。
(1)通過(guò)類.class屬性獲得。任何數(shù)據(jù)類型都有一個(gè)“靜態(tài)”的class屬性。Java在編譯一個(gè)類文件時(shí),會(huì)為該類動(dòng)態(tài)地添加一個(gè)公有的靜態(tài)常量屬性class,這個(gè)屬性記錄了該類的相關(guān)信息,即類型描述信息,它是Class類的實(shí)例。
(2)通過(guò)對(duì)象.getClass()方法獲得。任何對(duì)象都可以調(diào)用getClass()返回表示此對(duì)象運(yùn)行時(shí)類的Class對(duì)象。當(dāng)?shù)玫揭粋€(gè)對(duì)象引用而不知道所屬的類時(shí),就可以用此方法得到該對(duì)象所屬類的Class對(duì)象。
(3)通過(guò)Class.formName()靜態(tài)方法獲得。Java的Class提供了靜態(tài)方法formName(),此方法顯示地加載指定類,并返回被加載類的Class對(duì)象。
4 Constructor對(duì)象的獲取
Constructor類的對(duì)象用于描述類的單個(gè)構(gòu)造方法。Class對(duì)象提供了四個(gè)方法可以獲取Constructor對(duì)象。
(1)getConstructor(Class parameterTypes…)獲取指定參數(shù)類型的公有Constructor對(duì)象。
(2)getConstructors()獲取指定類的公有構(gòu)造方法描述對(duì)象Constructor列表。
(3)getDeclaredConstructor(Class parameterTypes…)獲取指定參數(shù)類型的構(gòu)造方法描述對(duì)象。
(4)getDeclaredConstructors()獲取指定類的所有構(gòu)造方法描述對(duì)象列表。
5 Method對(duì)象的獲取
Method類的對(duì)象用于描述類的單個(gè)方法(不包括構(gòu)造方法)??梢酝ㄟ^(guò)Method類來(lái)獲取方法的訪問(wèn)權(quán)限、參數(shù)類型、返回值類型等信息,并且可以通過(guò)獲取的Method對(duì)象來(lái)動(dòng)態(tài)執(zhí)行方法。Class對(duì)象提供了四個(gè)方法可以獲取Method對(duì)象。
(1)getMethod(String name,Class parameterTypes…)獲取指定名稱和參數(shù)類型的公有方法描述對(duì)象。
(2)getMethods()獲取公有的方法描述對(duì)象列表。
(3)getDeclaredMethod(String name, Class parameterTypes…)獲取指定名稱和參數(shù)類型的方法描述對(duì)象。
(4)getDeclaredMethods()獲取類本身定義的所有方法描述對(duì)象。
6 Field對(duì)象的獲取
Field類的對(duì)象用于描述類的單個(gè)屬性??梢酝ㄟ^(guò)Field對(duì)象來(lái)獲取屬性的訪問(wèn)權(quán)限、屬性類型等信息,并且可以通過(guò)獲取的Field對(duì)象來(lái)動(dòng)態(tài)地修改屬性值。Class對(duì)象也提供了四個(gè)方法可以獲取Field對(duì)象。
(1)getField(String name)獲取指定名稱的公有Field對(duì)象。
(2)getFields()獲取指定類的公有屬性描述對(duì)象Field列表。
(3)getDeclaredField(String name)獲取指定名稱的Field對(duì)象。
(4)getDeclaredFields()獲取指定類的所有屬性描述對(duì)象Field列表。
7反射的應(yīng)用
(1)運(yùn)行時(shí)類型識(shí)別
Class對(duì)象的isInstance()方法其原型是public boolean isInstance(Object obj),這個(gè)方法用來(lái)判定指定的對(duì)象是不是類的實(shí)例。例如從一個(gè)容器中取得了對(duì)象后,就可以判定這個(gè)對(duì)象的所屬的類。
(2)獲取資源文件的URL
Class對(duì)象的getResource()方法其原型是public URL getResource(String name),此方法可以返回與給定類相關(guān)的指定名稱的資源URL。如果程序中用到圖片、音頻等資源,可以將這些資源放到相關(guān)類字節(jié)碼文件相同目錄,便于程序打包成jar文件。
(3)動(dòng)態(tài)獲取類型信息
在程序中可以通過(guò)反射顯式加載指定類,通過(guò)反射實(shí)例化類,還可以通過(guò)反射執(zhí)行方法,修改屬性值和訪問(wèn)權(quán)限等操作。
8小結(jié)
Java中反射機(jī)制很實(shí)用,靈活使用反射能讓我們代碼更加靈活。但是反射也有缺點(diǎn),反射包括了一些動(dòng)態(tài)類型,所以 JVM 無(wú)法對(duì)這些代碼進(jìn)行優(yōu)化。因此,反射操作的效率要比那些非反射操作低得多。我們應(yīng)該避免在經(jīng)常被執(zhí)行的代碼或?qū)π阅芤蠛芨叩某绦蛑惺褂梅瓷鋄3]。
參考文獻(xiàn):
[1]Java基礎(chǔ)之—反射[EB/OL].[2018-03-17].http://blog.csdn.net/sinat_38259539/article/details/71799078
[2]徐傳運(yùn) 張楊.Java高級(jí)程序設(shè)計(jì)[M].北京:清華大學(xué)出版社,2014.
[3]粗淺看 java反射機(jī)制[EB/OL].[2018-03-17.http://blog.csdn.net/wsl211511/article/details/51605655