反射實例JAVA反射機制_第1頁
反射實例JAVA反射機制_第2頁
反射實例JAVA反射機制_第3頁
反射實例JAVA反射機制_第4頁
反射實例JAVA反射機制_第5頁
已閱讀5頁,還剩11頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、Java反射反射的概念是由Smith在1982年首次提出的,主要是指程序可以訪問、檢測和修改它本身狀態(tài)或行為的一種能力。這一概念的提出很快引發(fā)了計算機科學領(lǐng)域關(guān)于應(yīng)用反射性的研究。它首先被程序語言的設(shè)計領(lǐng)域所采用,并在Lisp和面向?qū)ο蠓矫嫒〉昧顺煽?。其中LEAD/LEAD+、OpenC+、MetaXa和OpenJava等就是基于反射機制的語言。最近,反射機制也被應(yīng)用到了視窗系統(tǒng)、操作系統(tǒng)和文件系統(tǒng)中。反射本身并不是一個新概念,它可能會使我們聯(lián)想到光學中的反射概念,盡管計算機科學賦予了反射概念新的含義,但是,從現(xiàn)象上來說,它們確實有某些相通之處,這些有助于我們的理解。在計算機科學領(lǐng)域,反射是指

2、一類應(yīng)用,它們能夠自描述和自控制。也就是說,這類應(yīng)用通過采用某種機制來實現(xiàn)對自己行為的描述(self-representation)和監(jiān)測(examination),并能根據(jù)自身行為的狀態(tài)和結(jié)果,調(diào)整或修改應(yīng)用所描述行為的狀態(tài)和相關(guān)的語義??梢钥闯?,同一般的反射概念相比,計算機科學領(lǐng)域的反射不單單指反射本身,還包括對反射結(jié)果所采取的措施。所有采用反射機制的系統(tǒng)(即反射系統(tǒng))都希望使系統(tǒng)的實現(xiàn)更開放??梢哉f,實現(xiàn)了反射機制的系統(tǒng)都具有開放性,但具有開放性的系統(tǒng)并不一定采用了反射機制,開放性是反射系統(tǒng)的必要條件。一般來說,反射系統(tǒng)除了滿足開放性條件外還必須滿足原因連接(Causally-conne

3、cted謂原因連接是指對反射系統(tǒng)自描述的改變能夠立即反映到系統(tǒng)底層的實際狀態(tài)和行為上的情況,反之亦然。開放性和原因連接是反射系統(tǒng)的兩大基本要素。Java中,反射是一種強大的工具。它使您能夠創(chuàng)建靈活的代碼,這些代碼可以在運行時裝配,無需在組件之間進行源代表鏈接。反射允許我們在編寫與執(zhí)行時,使我們的程序代碼能夠接入裝載到JVM中的類的內(nèi)部信息,而不是源代碼中選定的類協(xié)作的代碼。這使反射成為構(gòu)建靈活的應(yīng)用的主要工具。但需注意的是:如果使用不當,反射的成本很高。二、Java中的類反射:Reflection是Java程序開發(fā)語言的特征之一,它允許運行中的Java程序?qū)ψ陨磉M行檢查,或者說“自審”,并能直

4、接操作程序的內(nèi)部屬性。Java的這一能力在實際應(yīng)用中也許用得不是很多,但是在其它的程序設(shè)計語言中根本就不存在這一特性。例如,Pascal、C或者C+中就沒有辦法在程序中獲得函數(shù)定義相關(guān)的信息。1檢測類:1.1reflection的工作機制考慮下面這個簡單的例子,讓我們看看reflection是如何工作的。importjava.lang.reflect.*;publicclassDumpMethodspublicstaticvoidmain(Stringargs)tryClassc=Class.forName(args0);Methodm=c.getDeclaredMethods();for(i

5、nti=0;im.length;i+)System.out.println(mi.toString();catch(Throwablee)System.err.println(e);按如下語句執(zhí)行:javaDumpMethodsjava.util.Stack它的結(jié)果輸出為:publicjava.lang.Objectjava.util.Stack.push(java.lang.Object)publicsynchronizedjava.lang.Objectjava.util.Stack.pop()publicsynchronizedjava.lang.Objectjava.util.Stac

6、k.peek()publicbooleanjava.util.Stack.empty()publicsynchronizedintjava.util.Stack.search(java.lang.Object)這樣就列出了java.util.Stack類的各方法名以及它們的限制符和返回類型。這個程序使用Class.forName載入指定的類,然后調(diào)用getDeclaredMethods來獲取這個類中定義了的方法列表。java.Iang.reflect.Methods是用來描述某個類中單個方法的一個類。1.2Java類反射中的主要方法對于以下三類組件中的任何一類來說-構(gòu)造函數(shù)、字段和方法-jav

7、a.lang.Class提供四種獨立的反射調(diào)用,以不同的方式來獲得信息。調(diào)用都遵循一種標準格式。以下是用于查找構(gòu)造函數(shù)的一組反射調(diào)用:lConstructorgetConstructor(Classparams)-獲得使用特殊的參數(shù)類型的公共構(gòu)造函數(shù),lConstructorgetConstructors()-獲得類的所有公共構(gòu)造函數(shù)lConstructorgetDeclaredConstructor(Classparams)-獲得使用特定參數(shù)類型的構(gòu)造函數(shù)(與接入級別無關(guān))lConstructorgetDeclaredConstructors()-獲得類的所有構(gòu)造函數(shù)(與接入級別無關(guān))獲得字

8、段信息的Class反射調(diào)用不同于那些用于接入構(gòu)造函數(shù)的調(diào)用,在參數(shù)類型數(shù)組中使用了字段名:lFieldgetField(Stringname)-獲得命名的公共字段lFieldgetFields()-獲得類的所有公共字段lFieldgetDeclaredField(Stringname)-獲得類聲明的命名的字段lFieldgetDeclaredFields()-獲得類聲明的所有字段用于獲得方法信息函數(shù):lMethodgetMethod(Stringname,Classparams)-使用特定的參數(shù)類型,獲得命名的公共方法lMethodgetMethods()-獲得類的所有公共方法lMethodg

9、etDeclaredMethod(Stringname,Classparams)-使用特寫的參數(shù)類型,獲得類聲明的命名的方法lMethodgetDeclaredMethods()-獲得類聲明的所有方法1.3開始使用Reflection:用于reflection的類,女廿Method,可以在java.lang.relfect包中找到。使用這些類的時候必須要遵循三個步驟:第一步是獲得你想操作的類的java.lang.Class對象。在運行中的Java程序中,用java.lang.Class類來描述類和接口等。下面就是獲得一個Class對象的方法之一:Classc=Class.forName(jav

10、a.lang.String);這條語句得到一個String類的類對象。還有另一種方法,如下面的語句:Classc=int.class;或者Classc=Integer.TYPE;它們可獲得基本類型的類信息。其中后一種方法中訪問的是基本類型的封裝類(如Integer)中預(yù)先定義好的TYPE字段。第二步是調(diào)用諸如getDeclaredMethods的方法,以取得該類中定義的所有方法的列表。一旦取得這個信息,就可以進行第三步了使用reflectionAPI來操作這些信息,如下面這段代碼:Classc=Class.forName(java.lang.String);Methodm=c.getDecla

11、redMethods();System.out.println(m0.toString();它將以文本方式打印出String中定義的第一個方法的原型。2處理對象:如果要作一個開發(fā)工具像debugger之類的,你必須能發(fā)現(xiàn)filedvalues,以下是三個步驟:創(chuàng)建一個Class對象通過getField創(chuàng)建一個Field對象調(diào)用Field.getXXX(Object)方法(XXX是lnt,Float等,如果是對象就省略;Object是指實例).例如:importjava.lang.reflect.*;importjava.awt.*;classSampleGetpublicstaticvoidm

12、ain(Stringargs)Rectangler=newRectangle(100,325);printHeight(r);staticvoidprintHeight(Rectangler)FieldheightField;lntegerheightValue;Classc=r.getClass();tryheightField=c.getField(height);heightValue=(lnteger)heightField.get(r);System.out.println(Height:+heightValue.toString();catch(NoSuchFieldExcepti

13、one)System.out.println(e);catch(SecurityExceptione)System.out.println(e);catch(lllegalAccessExceptione)System.out.println(e);三、安全性和反射:在處理反射時安全性是一個較復雜的問題。反射經(jīng)常由框架型代碼使用,由于這一點,我們可能希望框架能夠全面接入代碼,無需考慮常規(guī)的接入限制。但是,在其它情況下,不受控制的接入會帶來嚴重的安全性風險,例如當代碼在不值得信任的代碼共享的環(huán)境中運行時。由于這些互相矛盾的需求,Java編程語言定義一種多級別方法來處理反射的安全性?;灸J绞菍Ψ?/p>

14、射實施與應(yīng)用于源代碼接入相同的限制:n從任意位置到類公共組件的接入n類自身外部無任何到私有組件的接入n受保護和打包(缺省接入)組件的有限接入不過至少有些時候,圍繞這些限制還有一種簡單的方法。我們可以在我們所寫的類中,擴展一個普通的基本類java.lang.reflect.AccessibleObject類。這個類定義了一種setAccessible方法,使我們能夠啟動或關(guān)閉對這些類中其中一個類的實例的接入檢測。唯一的問題在于如果使用了安全性管理器,它將檢測正在關(guān)閉接入檢測的代碼是否許可了這樣做。如果未許可,安全性管理器拋出一個例外。下面是一段程序,在TwoString類的一個實例上使用反射來顯

15、示安全性正在運行:publicclassReflectSecuritypublicstaticvoidmain(Stringargs)tryTwoStringts=newTwoString(a,b);Fieldfield=clas.getDeclaredField(m_s1);/field.setAccessible(true);System.out.println(Retrievedvalueis+field.get(inst);catch(Exceptionex)ex.printStackTrace(System.out);如果我們編譯這一程序時,不使用任何特定參數(shù)直接從命令行運行,它將在

16、field.get(inst)調(diào)用中拋出一個IIIegalAccessException異常。如果我們不注釋field.setAccessible(true)代碼行,那么重新編譯并重新運行該代碼,它將編譯成功。最后,如果我們在命令行添加了JVM參數(shù)-Djava.security.manager以實現(xiàn)安全性管理器,它仍然將不能通過編譯,除非我們定義了ReflectSecurity類的許可權(quán)限。四、反射性能:反射是一種強大的工具,但也存在一些不足。一個主要的缺點是對性能有影響。使用反射基本上是一種解釋操作,我們可以告訴JVM,我們希望做什么并且它滿足我們的要求。這類操作總是慢于只直接執(zhí)行相同的操作

17、。下面的程序是字段接入性能測試的一個例子,包括基本的測試方法。每種方法測試字段接入的一種形式-accessSame與同一對象的成員字段協(xié)作,accessOther使用可直接接入的另一對象的字段,accessReflection使用可通過反射接入的另一對象的字段。在每種情況下,方法執(zhí)行相同的計算-循環(huán)中簡單的加/乘順序。程序如下:publicintaccessSame(intloops)m_value=0;for(intindex=0;indexloops;index+)m_value=(m_value+ADDITIVE_VALUE)*MULTIPLIER_VALUE;returnm_value

18、;publicintaccessReference(intloops)TimingClasstiming=newTimingClass();for(intindex=0;indexloops;index+)timing.m_value=(timing.m_value+ADDITIVE_VALUE)*MULTIPLIER_VALUE;returntiming.m_value;publicintaccessReflection(intloops)throwsExceptionTimingClasstiming=newTimingClass();tryFieldfield=TimingClass.c

19、lass.getDeclaredField(m_value);for(intindex=0;indexloops;index+)intvalue=(field.getInt(timing)+ADDITIVE_VALUE)*MULTIPLIER_VALUE;field.setInt(timing,value);returntiming.m_value;catch(Exceptionex)System.out.println(Errorusingreflection);throwex;在上面的例子中,測試程序重復調(diào)用每種方法,使用一個大循環(huán)數(shù),從而平均多次調(diào)用的時間衡量結(jié)果。平均值中不包括每種方法

20、第一次調(diào)用的時間,因此初始化時間不是結(jié)果中的一個因素。下面的圖清楚的向我們展示了每種方法字段接入的時間:圖1:字段接入時間:我們可以看出:在前兩副圖中(SunJVM),使用反射的執(zhí)行時間超過使用直接接入的1000倍以上。通過比較,IBMJVM可能稍好一些,但反射方法仍舊需要比其它方法長700倍以上的時間。任何JVM上其它兩種方法之間時間方面無任何顯著差異,但IBMJVM幾乎比SunJVM快一倍。最有可能的是這種差異反映了SunHotSpotJVM的專業(yè)優(yōu)化,它在簡單基準方面表現(xiàn)得很糟糕。反射性能是Sun開發(fā)1.4JVM時關(guān)注的一個方面,它在反射方法調(diào)用結(jié)果中顯示。在這類操作的性能方面,Sun1

21、.4.1JVM顯示了比131版本很大的改進。如果為為創(chuàng)建使用反射的對象編寫了類似的計時測試程序,我們會發(fā)現(xiàn)這種情況下的差異不象字段和方法調(diào)用情況下那么顯著。使用newlnstance()調(diào)用創(chuàng)建一個簡單的java.Iang.Object實例耗用的時間大約是在Sun1.3.1JVM上使用newObject()的12倍,是在IBM140JVM的四倍,只是Sun1.4.1JVM上的兩部。使用Array.newlnstance(type,size)創(chuàng)建一個數(shù)組耗用的時間是任何測試的JVM上使用newtypesize的兩倍,隨著數(shù)組大小的增加,差異逐步縮小。結(jié)束語:Java語言反射提供一種動態(tài)鏈接程序組

22、件的多功能方法。它允許程序創(chuàng)建和控制任何類的對象(根據(jù)安全性限制),無需提前硬編碼目標類。這些特性使得反射特別適用于創(chuàng)建以非常普通的方式與對象協(xié)作的庫。例如,反射經(jīng)常在持續(xù)存儲對象為數(shù)據(jù)庫、XML或其它外部格式的框架中使用。Javareflection非常有用,它使類和數(shù)據(jù)結(jié)構(gòu)能按名稱動態(tài)檢索相關(guān)信息,并允許在運行著的程序中操作這些信息。Java的這一特性非常強大,并且是其它一些常用語言,如C、C+、Fortran或者Pascal等都不具備的。但反射有兩個缺點。第一個是性能問題。用于字段和方法接入時反射要遠慢于直接代碼。性能問題的程度取決于程序中是如何使用反射的。如果它作為程序運行中相對很少涉

23、及的部分,緩慢的性能將不會是一個問題。即使測試中最壞情況下的計時圖顯示的反射操作只耗用幾微秒。僅反射在性能關(guān)鍵的應(yīng)用的核心邏輯中使用時性能問題才變得至關(guān)重要。許多應(yīng)用中更嚴重的一個缺點是使用反射會模糊程序內(nèi)部實際要發(fā)生的事情。程序人員希望在源代碼中看到程序的邏輯,反射等繞過了源代碼的技術(shù)會帶來維護問題。反射代碼比相應(yīng)的直接代碼更復雜,正如性能比較的代碼實例中看到的一樣。解決這些問題的最佳方案是保守地使用反射僅在它可以真正增加靈活性的地方記錄其在目標類中的使用。最近在成都寫一個移動增值項目,俺負責后臺server端。功能很簡單,手機用戶通過GPRS打開Socket與服務(wù)器連接,我則根據(jù)用戶傳過來

24、的數(shù)據(jù)做出響應(yīng)。做過類似項目的兄弟一定都知道,首先需要定義一個類似于MSNP的通訊協(xié)議,不過今天的話題是如何把這個系統(tǒng)設(shè)計得具有高度的擴展性。由于這個項目本身沒有進行過較為完善的客戶溝通和需求分析,所以以后肯定會有很多功能上的擴展,通訊協(xié)議肯定會越來越龐大,而我作為一個不那么勤快的人,當然不想以后再去修改寫好的程序,所以這個項目是實踐面向?qū)ο笤O(shè)計的好機會。首先定義一個接口來隔離類:packageorg.bromon.reflect;publicinterfaceOperatorpublicjava.util.Listact(java.util.Listparams)根據(jù)設(shè)計模式的原理,我們可以

25、為不同的功能編寫不同的類,每個類都繼承Operator接口,客戶端只需要針對Operator接口編程就可以避免很多麻煩。比如這個類:packageorg.bromon.reflect.*;publicclassSuccessimplementsOperatorpublicjava.util.Listact(java.util.Listparams)Listresult=newArrayList();Java的反射機制是使其具有動態(tài)特性的非常關(guān)鍵的一種機制,也是在JavaBean中廣泛應(yīng)用的一種特性。運用JavaBean的最常見的問題是:根據(jù)指定的類名,類字段名和所對應(yīng)的數(shù)據(jù),得到該類的實例,下

26、面的一個例子演示了這一實現(xiàn)。-|Base.java/抽象基類|Son1.java/基類擴展1|Son2.java/基類擴展2|Util.java/*authormetaphycreate2005-4-149:06:56說明:*/(1)Base.java抽象基類只是一個定義publicabstractclassBase(2)Son1.java/Son2.java是已經(jīng)實現(xiàn)的JavaBeanpublicclassSon1extendsBaseprivateintid;privateStringname;publicintgetId()returnid;publicvoidsetId(intid)t

27、his.id=id;publicStringgetName()returnname;publicvoidsetName(Stringname)=name;publicvoidson1Method(Strings)System.out.println(s);(3)publicclassSon2extendsBaseprivateintid;privatedoublesalary;publicintgetId()returnid;publicvoidsetId(intid)this.id=id;publicdoublegetSalary()returnsalary;publicvoidsetSal

28、ary(doublesalary)this.salary=salary;(4)Util.java演示了如何根據(jù)指定的類名,類字段名和所對應(yīng)的數(shù)據(jù),得到一個類的實例importjava.lang.reflect.Method;publicclassUtil此方法的最大好處是沒有類名Son1,Son2可以通過參數(shù)來指定,程序里面根本不用出現(xiàn)publicstaticBaseconvertStr2ServiceBean(StringbeanName,StringfieldSetter,StringparaValue)Basebase=null;tryClasscls=Class.forName(bea

29、nName);base=(Base)cls.newInstance();ClassparaTypes=newClassString.class;Methodmethod=cls.getMethod(fieldSetter,paraTypes);StringparaValues=newStringparaValue;method.invoke(base,paraValues);catch(Throwablee)System.err.println(e);returnbase;publicstaticvoidmain(Stringargs)Son1son1=(Son1)Util.convertSt

30、r2ServiceBean(trying.reflect.Son1,setName,wangdasha);System.out.println(son1.getName():+son1.getName();/調(diào)用結(jié)果:/son1.getName():wangdasha謝謝!希望能給大家一點啟發(fā)!附:下面這篇文檔來源于Internet,作者不詳Reflection是Java程序開發(fā)語言的特征之一,它允許運行中的Java程序?qū)ψ陨磉M行檢查,或者說“自審”,并能直接操作程序的內(nèi)部屬性。例如,使用它能獲得Java類中各成員的名稱并顯示出來。Java的這一能力在實際應(yīng)用中也許用得不是很多,但是在其它的程

31、序設(shè)計語言中根本就不存在這一特性。例如,Pascal、C或者C+中就沒有辦法在程序中獲得函數(shù)定義相關(guān)的信息。JavaBean是reflection的實際應(yīng)用之一,它能讓一些工具可視化的操作軟件組件。這些工具通過reflection動態(tài)的載入并取得Java組件(類)的屬性。1.一個簡單的例子考慮下面這個簡單的例子,讓我們看看reflection是如何工作的。importjava.lang.reflect.*;publicclassDumpMethodspublicstaticvoidmain(Stringargs)tryClassc=Class.forName(args0);Methodm=c.

32、getDeclaredMethods();for(inti=0;im.length;i+)System.out.println(mi.toString();catch(Throwablee)System.err.println(e);按如下語句執(zhí)行:javaDumpMethodsjava.util.Stack它的結(jié)果輸出為:publicjava.lang.Objectjava.util.Stack.push(java.lang.Object)publicsynchronizedjava.lang.Objectjava.util.Stack.pop()publicsynchronizedjava

33、.lang.Objectjava.util.Stack.peek()publicbooleanjava.util.Stack.empty()publicsynchronizedintjava.util.Stack.search(java.lang.Object)這樣就列出了java.util.Stack類的各方法名以及它們的限制符和返回類型。這個程序使用Class.forName載入指定的類,然后調(diào)用getDeclaredMethods來獲取這個類中定義了的方法列表。java.Iang.reflect.Methods是用來描述某個類中單個方法的一個類。2.開始使用Reflection用于ref

34、lection的類,女廿Method,可以在java.lang.relfect包中找到。使用這些類的時候必須要遵循三個步驟:第一步是獲得你想操作的類的java.lang.Class對象。在運行中的Java程序中,用java.lang.Class類來描述類和接口等。下面就是獲得一個Class對象的方法之一:Classc=Class.forName(java.lang.String);這條語句得到一個String類的類對象。還有另一種方法,如下面的語句:Classc=int.class;或者Classc=Integer.TYPE;它們可獲得基本類型的類信息。其中后一種方法中訪問的是基本類型的封裝類

35、(如Integer)中預(yù)先定義好的TYPE字段。第二步是調(diào)用諸如getDeclaredMethods的方法,以取得該類中定義的所有方法的列表。一旦取得這個信息,就可以進行第三步了使用reflectionAPI來操作這些信息,如下面這段代碼:Classc=Class.forName(java.lang.String);Methodm=c.getDeclaredMethods();System.out.println(m0.toString();它將以文本方式打印出String中定義的第一個方法的原型。在下面的例子中,這三個步驟將為使用reflection處理特殊應(yīng)用程序提供例證。模擬instan

36、ceof操作符得到類信息之后,通常下一個步驟就是解決關(guān)于Class對象的一些基本的問題。例如,Class.isInstance方法可以用于模擬instanceof操作符:classApublicclassinstance1publicstaticvoidmain(Stringargs)tryClasscls=Class.forName(A);booleanb1=cls.isInstance(newInteger(37);System.out.println(b1);booleanb2=cls.isInstance(newA();System.out.println(b2);catch(Thro

37、wablee)System.err.println(e);在這個例子中創(chuàng)建了一個A類的Class對象,然后檢查一些對象是否是A的實例。Integer(37)不是,但newA()是。3.找出類的方法找出一個類中定義了些什么方法,這是一個非常有價值也非常基礎(chǔ)的reflection用法。下面的代碼就實現(xiàn)了這一用法:importjava.lang.reflect.*;publicclassmethod1privateintf1(Objectp,intx)throwsNullPointerExceptionif(p=null)thrownewNullPointerException();returnx;

38、publicstaticvoidmain(Stringargs)tryClasscls=Class.forName(method1);Methodmethlist=cls.getDeclaredMethods();for(inti=0;imethlist.length;i+)Methodm=methlisti;System.out.println(name=+m.getName();System.out.println(declclass=+m.getDeclaringClass();Classpvec=m.getParameterTypes();for(intj=0;jpvec.length

39、;j+)System.out.println(param#+j+pvecj);Classevec=m.getExceptionTypes();for(intj=0;jevec.length;j+)System.out.println(exc#+j+evecj);System.out.println(returntype=+m.getReturnType();System.out.println();catch(Throwablee)System.err.println(e);這個程序首先取得method1類的描述,然后調(diào)用getDeclaredMethods來獲取一系列的Method對象,它們

40、分別描述了定義在類中的每一個方法,包括public方法protected方法package方法和private方法等。如果你在程序中使用getMethods來代替getDeclaredMethods,你還能獲得繼承來的各個方法的信息。取得了Method對象列表之后,要顯示這些方法的參數(shù)類型、異常類型和返回值類型等就不難了。這些類型是基本類型還是類類型,都可以由描述類的對象按順序給出。輸出的結(jié)果如下:name=f1declclass=classmethod1param#0classjava.lang.Objectparam#1intexc#0classjava.lang.NullPointerE

41、xceptionreturntype=intname=maindeclclass=classmethod1param#0classLjava.lang.String;returntype=void4.獲取構(gòu)造器信息獲取類構(gòu)造器的用法與上述獲取方法的用法類似,如:importjava.lang.reflect.*;publicclassconstructor1publicconstructor1()protectedconstructor1(inti,doubled)publicstaticvoidmain(Stringargs)tryClasscls=Class.forName(constru

42、ctor1);Constructorctorlist=cls.getDeclaredConstructors();for(inti=0;ictorlist.length;i+)Constructorct=ctorlisti;System.out.println(name=+ct.getName();System.out.println(declclass=+ct.getDeclaringClass();Classpvec=ct.getParameterTypes();for(intj=0;jpvec.length;j+)System.out.println(param#+j+pvecj);Cl

43、assevec=ct.getExceptionTypes();for(intj=0;jevec.length;j+)System.out.println(exc#+j+evecj);System.out.println();catch(Throwablee)System.err.println(e);這個例子中沒能獲得返回類型的相關(guān)信息,那是因為構(gòu)造器沒有返回類型這個程序運行的結(jié)果是:name=constructor1declclass=classconstructor1name=constructor1declclass=classconstructor1param#0intparam#1d

44、ouble5.獲取類的字段(域)找出一個類中定義了哪些數(shù)據(jù)字段也是可能的,下面的代碼就在干這個事情:importjava.lang.reflect.*;publicclassfield1privatedoubled;publicstaticfinalinti=37;Strings=testing;publicstaticvoidmain(Stringargs)tryClasscls=Class.forName(field1);Fieldfieldlist=cls.getDeclaredFields();for(inti=0;ifieldlist.length;i+)Fieldfld=field

45、listi;System.out.println(name=+fld.getName();System.out.println(declclass=+fld.getDeclaringClass();System.out.println(type=+fld.getType();intmod=fld.getModifiers();System.out.println(modifiers=+Modifier.toString(mod);System.out.println();catch(Throwablee)System.err.println(e);這個例子和前面那個例子非常相似。例中使用了一個

46、新東西Modifier,它也是一個reflection類,用來描述字段成員的修飾語,如privateint。這些修飾語自身由整數(shù)描述,而且使用Modifier.toString來返回以“官方”順序排列的字符串描述(如static在final之前)。這個程序的輸出是:name=ddeclclass=classfield1type=doublemodifiers=privatename=ideclclass=classfield1type=intmodifiers=publicstaticfinalname=sdeclclass=classfield1type=classjava.lang.Str

47、ingmodifiers=和獲取方法的情況一下,獲取字段的時候也可以只取得在當前類中申明了的字段信息(getDeclaredFields),或者也可以取得父類中定義的字段(getFields)。根據(jù)方法的名稱來執(zhí)行方法文本到這里,所舉的例子無一例外都與如何獲取類的信息有關(guān)。我們也可以用reflection來做一些其它的事情,比如執(zhí)行一個指定了名稱的方法。下面的示例演示了這一操作:importjava.lang.reflect.*;publicclassmethod2publicintadd(inta,intb)returna+b;publicstaticvoidmain(Stringargs)

48、tryClasscls=Class.forName(method2);Classpartypes=newClass2;partypes0=Integer.TYPE;partypes1=Integer.TYPE;Methodmeth=cls.getMethod(add,partypes);method2methobj=newmethod2();Objectarglist=newObject2;arglist0=newInteger(37);arglist1=newInteger(47);Objectretobj=meth.invoke(methobj,arglist);Integerretval

49、=(Integer)retobj;System.out.println(value();catch(Throwablee)System.err.println(e);假如一個程序在執(zhí)行的某處的時候才知道需要執(zhí)行某個方法,這個方法的名稱是在程序的運行過程中指定的(例如,JavaBean開發(fā)環(huán)境中就會做這樣的事),那么上面的程序演示了如何做到。上例中,getMethod用于查找一個具有兩個整型參數(shù)且名為add的方法。找到該方法并創(chuàng)建了相應(yīng)的Method對象之后,在正確的對象實例中執(zhí)行它。執(zhí)行該方法的時候,需要提供一個參數(shù)列表,這在上例中是分別包裝了整數(shù)37和47的兩個Integer對象。執(zhí)行方法的

50、返回的同樣是一個Integer對象,它封裝了返回值84。創(chuàng)建新的對象對于構(gòu)造器,則不能像執(zhí)行方法那樣進行,因為執(zhí)行一個構(gòu)造器就意味著創(chuàng)建了一個新的對象(準確的說,創(chuàng)建一個對象的過程包括分配內(nèi)存和構(gòu)造對象)。所以,與上例最相似的例子如下:importjava.lang.reflect.*;publicclassconstructor2publicconstructor2()publicconstructor2(inta,intb)System.out.println(a=+a+b=+b);publicstaticvoidmain(Stringargs)tryClasscls=Class.forName(constructor2);Classpartypes=newClass2;partypes0=Integer.TYPE;

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論