天天看點

[Java開發之路]反射機制

簡介

java反射機制是在運作狀态中,對于任意一個類,都能夠知道這個類的所有屬性和方法;對于任意一個對象,都能夠調用它的任意一個方法和屬性;這種動态擷取的資訊以及動态調用對象的方法的功能稱為java語言的反射機制。

java反射機制:“程式運作時,允許改變程式結構或變量類型,這種語言稱為動态語言”。從這個觀點看,perl,python,ruby是動态語言,c++,java,c#不是動态語言。但是java有着一個非常突出的動态相關機制:reflection,用在java身上指的是我們可以于運作時加載、探知、使用編譯期間完全未知的classes。換句話說,java程式可以加載一個運作時才得知名稱的class,獲悉其完整構造(但不包括methods定義),并生成其對象實體、或對其fields設值、或喚起其methods。

反射基礎

反射提供了一種動态的功能,這種動态功能非常的強大。它主要展現在通過反射相關的api,就可以知道一個陌生的java類的所有資訊,包括屬性,方法,構造器等。而且元素完全可以在運作時動态的進行建立或調用,而不必在jvm運作時就進行确定。

反射原理

嚴格意義上說,java并不是動态語言,它并沒有perl和python那樣的靈活多變。但是,java的反射機制卻讓它顯得動态起來。

一般情況下,如果想生成這個類的對象時,運作這個程式的jvm會确認這個類的class對象是否已經加載。如果尚未加載,jvm會根據類名查找class檔案,并将其載入,一旦這個類的class對象被載入記憶體,它就可以被用來建立這個類的所有對象。

另外,對于一個未知類型的引用來說,通常會采用強制類型轉換的形式得到開發者想要的類型引用,如果執行了一個錯誤的類型轉換,就會抛出一個classcastexception異常。

在以上這兩個過程中,class類一直都在起作用。因為class類執行個體包含的是一個java類的全部資訊,包括類名,方法,屬性等。換句話說,也就是class對象就是代表一個類的類。

java用class類來代表所有的類,友善了開發者掌控類資訊。通過class,開發者可以得到屬性,方法,構造器,修飾符等資訊。在動态的 擷取這些資訊以後,開發者就可以用該class建立執行個體,調用任何方法,通路任何屬性等操作,這些也是反射的主要用途。

反射機制相關的api主要集中在java.lang.reflect包下,開發者也就是利用該包下面的接口和類進行相關的反射開發的。大多數的架構,如struts,hibernate,和spring,都會頻繁的使用反射api來完成他們的動态的功能。

反射是為了能夠動态的加載一個類,動态的調用一個方法,動态的房屋内一個屬性等動态要求而設計的。它的出發點就在于jvm會為每個類建立一個java.lang.class類的執行個體,通過該對象可以擷取這個類的資訊,然後通過使用java.lang.reflect包下的api以達到各種動态需求。

class類含義與作用

class類在反射機制中起到了非常關鍵的作用,它是開發者進行反射開發的入口。那應該如何擷取一個類的class對象呢?如何讓一個類動态的加載到jvm中呢?

在前面的内容中,讀者知道了class是用來記錄一個類的各種資訊的,它伴随着類的加載而建立。那麼,類會在什麼時候加載到jvm中呢?概括的來說,一個普通的java類,會在一下幾種情況,被加載到jvm中。

(1)需要使用該類建立對象。如下代碼就會導緻student類被加載到jvm中:

(2)通路該類的靜态成員。

(3)使用class類的靜态forname()方法,動态的加載一個指定類名的類。如果類未找到,則抛出classnotfoundexception異常。

不管通過社麼樣的形式,類一旦被加載進入jvm以後,就會為它建立一個class類的執行個體對象。那麼,開發者又該如何得到這個class對象呢?概括來說,要得到一個類的class對象,可以通過以下幾種途徑。

(1)class的forname()方法的傳回值就是class類型,也就是動态導入類的class對象的引用。

(2)每個類都會有一個名稱為class的靜态屬性,通過它也是可以擷取到class對象的。

(3)object類中有一個名為getclass的成員方法,它傳回的是對象運作時類的class對象。因為onject類是所有類的父類,是以,所有的對象都可以使用該方法得到它運作時類的class對象。

擷取到class對象以後,就可以通過調用它的一些成員方法擷取它所代表的類的屬性,方法,修飾符等資訊,以及調用newinstance()方法來建立新的執行個體對象。