Java反射機(jī)制是Java語言的一個重要特性。在學(xué)習(xí)Java反射機(jī)制前,大家應(yīng)該先了解兩個概念,編譯期和運行期。
編譯期是指把源碼交給編譯器編譯成計算機(jī)可以執(zhí)行的文件的過程。在Java中也就是把Java代碼編成class文件的過程。編譯期只是做了一些翻譯功能,并沒有把代碼放在內(nèi)存中運行起來,而只是把代碼當(dāng)成文本進(jìn)行操作,比如檢查錯誤。
運行期是把編譯后的文件交給計算機(jī)執(zhí)行,直到程序運行結(jié)束。所謂運行期就把在磁盤中的代碼放到內(nèi)存中執(zhí)行起來。
Java反射機(jī)制是在運行狀態(tài)中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調(diào)用它的任意方法和屬性;這種動態(tài)獲取信息以及動態(tài)調(diào)用對象方法的功能稱為Java語言的反射機(jī)制。簡單來說,反射機(jī)制指的是程序在運行時能夠獲取自身的信息。在Java中,只要給定類的名字,就可以通過反射機(jī)制來獲得類的所有信息。
Java反射機(jī)制在服務(wù)器程序和中間件程序中得到了廣泛運用。在服務(wù)器端,往往需要根據(jù)客戶的請求,動態(tài)調(diào)用某一個對象的特定方法。此外,在ORM中間件的實現(xiàn)中,運用Java反射機(jī)制可以讀取任意一個JavaBean的所有屬性,或者給這些屬性賦值。
Java反射機(jī)制主要提供了以下功能,這些功能都位于java.lang.reflect包。
在運行時判斷任意一個對象所屬的類。
在運行時構(gòu)造任意一個類的對象。
在運行時判斷任意一個類所具有的成員變量和方法。
在運行時調(diào)用任意一個對象的方法。
生成動態(tài)代理。
要想知道一個類的屬性和方法,必須先獲取到該類的字節(jié)碼文件對象。獲取類的信息時,使用的就是Class類中的方法。所以先要獲取到每一個字節(jié)碼文件(.class)對應(yīng)的Class類型的對象.
眾所周知,所有Java類均繼承了Object類,在Object類中定義了一個getClass()方法,該方法返回同一個類型為Class的對象。例如,下面的示例代碼:
Class labelCls = label1.getClass(); // label1為 JLabel 類的對象1復(fù)制代碼類型:[java]
利用Class類的對象labelCls可以訪問labelCls對象的描述信息、JLabel類的信息以及基類Object的信息。表1列出了通過反射可以訪問的信息。
表1反射可訪問的常用信息
類型 | 訪問方法 | 返回值類型 | 說明 |
---|---|---|---|
包路徑 | getPackage() | Package 對象 | 獲取該類的存放路徑 |
類名稱 | getName() | String 對象 | 獲取該類的名稱 |
繼承類 | getSuperclass() | Class 對象 | 獲取該類繼承的類 |
實現(xiàn)接口 | getlnterfaces() | Class 型數(shù)組 | 獲取該類實現(xiàn)的所有接口 |
構(gòu)造方法 | getConstructors() | Constructor 型數(shù)組 | 獲取所有權(quán)限為 public 的構(gòu)造方法 |
getDeclaredContruectors() | Constructor 對象 | 獲取當(dāng)前對象的所有構(gòu)造方法 | |
方法 | getMethods() | Methods 型數(shù)組 | 獲取所有權(quán)限為 public 的方法 |
getDeclaredMethods() | Methods 對象 | 獲取當(dāng)前對象的所有方法 | |
成員變量 | getFields() | Field 型數(shù)組 | 獲取所有權(quán)限為 public 的成員變量 |
getDeclareFileds() | Field 對象 | 獲取當(dāng)前對象的所有成員變量 | |
內(nèi)部類 | getClasses() | Class 型數(shù)組 | 獲取所有權(quán)限為 public 的內(nèi)部類 |
getDeclaredClasses() | Class 型數(shù)組 | 獲取所有內(nèi)部類 | |
內(nèi)部類的聲明類 | getDeclaringClass() | Class 對象 | 如果該類為內(nèi)部類,則返回它的成員類,否則返回 null |
如表1所示,在調(diào)用getFields()和getMethods()方法時將會依次獲取權(quán)限為public的字段和變量,然后將包含從超類中繼承到的成員變量和方法。而通過getDeclareFields()和getDeclareMethod()只是獲取在本類中定義的成員變量和方法。
優(yōu)點:
能夠運行時動態(tài)獲取類的實例,大大提高系統(tǒng)的靈活性和擴(kuò)展性。
與Java動態(tài)編譯相結(jié)合,可以實現(xiàn)無比強(qiáng)大的功能。
對于Java這種先編譯再運行的語言,能夠讓我們很方便的創(chuàng)建靈活的代碼,這些代碼可以在運行時裝配,無需在組件之間進(jìn)行源代碼的鏈接,更加容易實現(xiàn)面向?qū)ο蟆?/p>
缺點:
反射會消耗一定的系統(tǒng)資源,因此,如果不需要動態(tài)地創(chuàng)建一個對象,那么就不需要用反射;
反射調(diào)用方法時可以忽略權(quán)限檢查,獲取這個類的私有方法和屬性,因此可能會破壞類的封裝性而導(dǎo)致安全問題。
Java反射機(jī)制在一般的Java應(yīng)用開發(fā)中很少使用,即便是JavaEE階段也很少使用。