java(教學(xué)0)-java反射機(jī)制與動(dòng)態(tài)代理_第1頁
java(教學(xué)0)-java反射機(jī)制與動(dòng)態(tài)代理_第2頁
java(教學(xué)0)-java反射機(jī)制與動(dòng)態(tài)代理_第3頁
java(教學(xué)0)-java反射機(jī)制與動(dòng)態(tài)代理_第4頁
java(教學(xué)0)-java反射機(jī)制與動(dòng)態(tài)代理_第5頁
已閱讀5頁,還剩93頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

Java反射機(jī)制與動(dòng)態(tài)代理版權(quán)歸浪曦視頻在線所有Java反射機(jī)制與動(dòng)態(tài)代理版權(quán)歸浪曦視第2頁概述本課程主要講述Java反射機(jī)制與設(shè)計(jì)模式之一:代理模式的原理與應(yīng)用同時(shí)詳細(xì)講述了Java對(duì)代理模式的支持以及Java中動(dòng)態(tài)代理的原理,應(yīng)用與實(shí)踐本課程要求大家對(duì)Java泛型知識(shí)有所了解,因?yàn)槌绦虼a中大量使用了泛型相關(guān)知識(shí),對(duì)于不熟悉該部分內(nèi)容的讀者,我會(huì)在下次課程中對(duì)JDK5.0中的新特性進(jìn)行講解第2頁概述本課程主要講述Java反射機(jī)制與設(shè)計(jì)模式第3頁目錄Java反射機(jī)制代理模式第3頁目錄Java反射機(jī)制第4頁Java語言的反射機(jī)制在Java運(yùn)行時(shí)環(huán)境中,對(duì)于任意一個(gè)類,能否知道這個(gè)類有哪些屬性和方法?對(duì)于任意一個(gè)對(duì)象,能否調(diào)用它的任意一個(gè)方法?答案是肯定的。這種動(dòng)態(tài)獲取類的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能來自于Java語言的反射(Reflection)機(jī)制。Java反射機(jī)制主要提供了以下功能第4頁Java語言的反射機(jī)制在Java運(yùn)行時(shí)環(huán)境中,對(duì)于任第5頁Java語言的反射機(jī)制在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類。在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象。在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法。在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法第5頁Java語言的反射機(jī)制在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的第6頁Java語言的反射機(jī)制Reflection是Java被視為動(dòng)態(tài)(或準(zhǔn)動(dòng)態(tài))語言的一個(gè)關(guān)鍵性質(zhì)。這個(gè)機(jī)制允許程序在運(yùn)行時(shí)透過ReflectionAPIs取得任何一個(gè)已知名稱的class的內(nèi)部信息,包括其modifiers(諸如public,static等等)、superclass(例如Object)、實(shí)現(xiàn)之interfaces(例如Serializable),也包括fields和methods的所有信息,并可于運(yùn)行時(shí)改變fields內(nèi)容或調(diào)用methods第6頁Java語言的反射機(jī)制Reflection是Jav第7頁Java語言的反射機(jī)制一般而言,開發(fā)者社群說到動(dòng)態(tài)語言,大致認(rèn)同的一個(gè)定義是:“程序運(yùn)行時(shí),允許改變程序結(jié)構(gòu)或變量類型,這種語言稱為動(dòng)態(tài)語言”。從這個(gè)觀點(diǎn)看,Perl,Python,Ruby是動(dòng)態(tài)語言,C++,Java,C#不是動(dòng)態(tài)語言第7頁Java語言的反射機(jī)制一般而言,開發(fā)者社群說到動(dòng)態(tài)語第8頁Java語言的反射機(jī)制盡管在這樣的定義與分類下Java不是動(dòng)態(tài)語言,它卻有著一個(gè)非常突出的動(dòng)態(tài)相關(guān)機(jī)制:Reflection。這個(gè)字的意思是“反射、映象、倒影”,用在Java身上指的是我們可以于運(yùn)行時(shí)加載、探知、使用編譯期間完全未知的classes。換句話說,Java程序可以加載一個(gè)運(yùn)行時(shí)才得知名稱的class,獲悉其完整構(gòu)造(但不包括methods定義),并生成其對(duì)象實(shí)體、或?qū)ζ鋐ields設(shè)值、或喚起其methods。這種“看透class”的能力(theabilityoftheprogramtoexamineitself)被稱為introspection(內(nèi)省、內(nèi)觀、反省)。Reflection和introspection是常被并提的兩個(gè)術(shù)語第8頁Java語言的反射機(jī)制盡管在這樣的定義與分類下Jav第9頁JavaReflectionAPI簡介在JDK中,主要由以下類來實(shí)現(xiàn)Java反射機(jī)制,這些類都位于java.lang.reflect包中Class類:代表一個(gè)類。Field類:代表類的成員變量(成員變量也稱為類的屬性)。Method類:代表類的方法。Constructor類:代表類的構(gòu)造方法。Array類:提供了動(dòng)態(tài)創(chuàng)建數(shù)組,以及訪問數(shù)組的元素的靜態(tài)方法第9頁JavaReflectionAPI簡介在JDK中第10頁JavaReflectionAPI簡介例程DumpMethods類演示了ReflectionAPI的基本作用,它讀取命令行參數(shù)指定的類名,然后打印這個(gè)類所具有的方法信息第10頁JavaReflectionAPI簡介例程Du第11頁JavaReflectionAPI簡介例程ReflectTester類進(jìn)一步演示了ReflectionAPI的基本使用方法。ReflectTester類有一個(gè)copy(Objectobject)方法,這個(gè)方法能夠創(chuàng)建一個(gè)和參數(shù)object同樣類型的對(duì)象,然后把object對(duì)象中的所有屬性拷貝到新建的對(duì)象中,并將它返回這個(gè)例子只能復(fù)制簡單的JavaBean,假定JavaBean的每個(gè)屬性都有public類型的getXXX()和setXXX()方法。第11頁JavaReflectionAPI簡介例程Re第12頁JavaReflectionAPI簡介ReflectTester類的copy(Objectobject)方法依次執(zhí)行以下步驟(1)獲得對(duì)象的類型:ClassclassType=object.getClass();System.out.println("Class:"+classType.getName());第12頁JavaReflectionAPI簡介Refl第13頁JavaReflectionAPI簡介在java.lang.Object類中定義了getClass()方法,因此對(duì)于任意一個(gè)Java對(duì)象,都可以通過此方法獲得對(duì)象的類型。Class類是ReflectionAPI中的核心類,它有以下方法getName():獲得類的完整名字。getFields():獲得類的public類型的屬性。getDeclaredFields():獲得類的所有屬性。getMethods():獲得類的public類型的方法。getDeclaredMethods():獲得類的所有方法。第13頁JavaReflectionAPI簡介在jav第14頁JavaReflectionAPI簡介getMethod(Stringname,Class[]parameterTypes):獲得類的特定方法,name參數(shù)指定方法的名字,parameterTypes參數(shù)指定方法的參數(shù)類型。getConstructors():獲得類的public類型的構(gòu)造方法。getConstructor(Class[]parameterTypes):獲得類的特定構(gòu)造方法,parameterTypes參數(shù)指定構(gòu)造方法的參數(shù)類型。newInstance():通過類的不帶參數(shù)的構(gòu)造方法創(chuàng)建這個(gè)類的一個(gè)對(duì)象。第14頁JavaReflectionAPI簡介getM第15頁JavaReflectionAPI簡介(2)通過默認(rèn)構(gòu)造方法創(chuàng)建一個(gè)新對(duì)象:ObjectobjectCopy=classType.getConstructor(newClass[]{}).newInstance(newObject[]{});以上代碼先調(diào)用Class類的getConstructor()方法獲得一個(gè)Constructor對(duì)象,它代表默認(rèn)的構(gòu)造方法,然后調(diào)用Constructor對(duì)象的newInstance()方法構(gòu)造一個(gè)實(shí)例。第15頁JavaReflectionAPI簡介(2)通第16頁JavaReflectionAPI簡介(3)獲得對(duì)象的所有屬性:Fieldfields[]=classType.getDeclaredFields();Class類的getDeclaredFields()方法返回類的所有屬性,包括public、protected、默認(rèn)和private訪問級(jí)別的屬性第16頁JavaReflectionAPI簡介(3)獲第17頁JavaReflectionAPI簡介(4)獲得每個(gè)屬性相應(yīng)的getXXX()和setXXX()方法,然后執(zhí)行這些方法,把原來對(duì)象的屬性拷貝到新的對(duì)象中第17頁JavaReflectionAPI簡介(4)獲第18頁JavaReflectionAPI簡介在例程InvokeTester類的main()方法中,運(yùn)用反射機(jī)制調(diào)用一個(gè)InvokeTester對(duì)象的add()和echo()方法第18頁JavaReflectionAPI簡介在例程I第19頁JavaReflectionAPI簡介add()方法的兩個(gè)參數(shù)為int類型,獲得表示add()方法的Method對(duì)象的代碼如下:MethodaddMethod=classType.getMethod("add",newClass[]{int.class,int.class});Method類的invoke(Objectobj,Objectargs[])方法接收的參數(shù)必須為對(duì)象,如果參數(shù)為基本類型數(shù)據(jù),必須轉(zhuǎn)換為相應(yīng)的包裝類型的對(duì)象。invoke()方法的返回值總是對(duì)象,如果實(shí)際被調(diào)用的方法的返回類型是基本類型數(shù)據(jù),那么invoke()方法會(huì)把它轉(zhuǎn)換為相應(yīng)的包裝類型的對(duì)象,再將其返回第19頁JavaReflectionAPI簡介add(第20頁JavaReflectionAPI簡介在本例中,盡管InvokeTester類的add()方法的兩個(gè)參數(shù)以及返回值都是int類型,調(diào)用addMethod對(duì)象的invoke()方法時(shí),只能傳遞Integer類型的參數(shù),并且invoke()方法的返回類型也是Integer類型,Integer類是int基本類型的包裝類:Objectresult=addMethod.invoke(invokeTester,newObject[]{newInteger(100),newInteger(200)});System.out.println((Integer)result);//result為Integer類型第20頁JavaReflectionAPI簡介在本例中第21頁JavaReflectionAPI簡介java.lang.Array類提供了動(dòng)態(tài)創(chuàng)建和訪問數(shù)組元素的各種靜態(tài)方法。例程ArrayTester1類的main()方法創(chuàng)建了一個(gè)長度為10的字符串?dāng)?shù)組,接著把索引位置為5的元素設(shè)為“hello”,然后再讀取索引位置為5的元素的值第21頁JavaReflectionAPI簡介java第22頁JavaReflectionAPI簡介例程ArrayTester2類的main()方法創(chuàng)建了一個(gè)5x10x15的整型數(shù)組,并把索引位置為[3][5][10]的元素的值為設(shè)37第22頁JavaReflectionAPI簡介例程Ar第23頁“Class” class眾所周知Java有個(gè)Objectclass,是所有Javaclasses的繼承根源,其內(nèi)聲明了數(shù)個(gè)應(yīng)該在所有Javaclass中被改寫的methods:hashCode()、equals()、clone()、toString()、getClass()等。其中g(shù)etClass()返回一個(gè)Classobject。第23頁“Class” class眾所周知Java有個(gè)O第24頁“Class” classClassclass十分特殊。它和一般classes一樣繼承自O(shè)bject,其實(shí)體用以表達(dá)Java程序運(yùn)行時(shí)的classes和interfaces,也用來表達(dá)enum、array、primitiveJavatypes(boolean,byte,char,short,int,long,float,double)以及關(guān)鍵詞void。當(dāng)一個(gè)class被加載,或當(dāng)加載器(classloader)的defineClass()被JVM調(diào)用,JVM便自動(dòng)產(chǎn)生一個(gè)Classobject。如果您想借由“修改Java標(biāo)準(zhǔn)庫源碼”來觀察Classobject的實(shí)際生成時(shí)機(jī)(例如在Class的constructor內(nèi)添加一個(gè)println()),不能夠!因?yàn)镃lass并沒有publicconstructor第24頁“Class” classClassclass第25頁“Class” classClass是Reflection起源。針對(duì)任何您想探勘的class,唯有先為它產(chǎn)生一個(gè)Classobject,接下來才能經(jīng)由后者喚起為數(shù)十多個(gè)的ReflectionAPIs第25頁“Class” classClass是Refle第26頁“Class”object的取得途徑Java允許我們從多種途徑為一個(gè)class生成對(duì)應(yīng)的Classobject第26頁“Class”object的取得途徑Java允許我第27頁“Class”object的取得途徑第27頁“Class”object的取得途徑第28頁運(yùn)行時(shí)生成instances欲生成對(duì)象實(shí)體,在Reflection動(dòng)態(tài)機(jī)制中有兩種作法,一個(gè)針對(duì)“無自變量ctor”,一個(gè)針對(duì)“帶參數(shù)ctor”。如果欲調(diào)用的是“帶參數(shù)ctor“就比較麻煩些,不再調(diào)用Class的newInstance(),而是調(diào)用Constructor的newInstance()。首先準(zhǔn)備一個(gè)Class[]做為ctor的參數(shù)類型(本例指定為一個(gè)double和一個(gè)int),然后以此為自變量調(diào)用getConstructor(),獲得一個(gè)專屬ctor。接下來再準(zhǔn)備一個(gè)Object[]做為ctor實(shí)參值(本例指定3.14159和125),調(diào)用上述專屬ctor的newInstance()。第28頁運(yùn)行時(shí)生成instances欲生成對(duì)象實(shí)體,在Ref第29頁運(yùn)行時(shí)生成instances動(dòng)態(tài)生成“Classobject所對(duì)應(yīng)之class”的對(duì)象實(shí)體;無自變量。第29頁運(yùn)行時(shí)生成instances動(dòng)態(tài)生成“Classo第30頁運(yùn)行時(shí)生成instances第30頁運(yùn)行時(shí)生成instances第31頁運(yùn)行時(shí)調(diào)用methods這個(gè)動(dòng)作和上述調(diào)用“帶參數(shù)之ctor”相當(dāng)類似。首先準(zhǔn)備一個(gè)Class[]做為參數(shù)類型(本例指定其中一個(gè)是String,另一個(gè)是Hashtable),然后以此為自變量調(diào)用getMethod(),獲得特定的Methodobject。接下來準(zhǔn)備一個(gè)Object[]放置自變量,然后調(diào)用上述所得之特定Methodobject的invoke()。為什么獲得Methodobject時(shí)不需指定回返類型?第31頁運(yùn)行時(shí)調(diào)用methods這個(gè)動(dòng)作和上述調(diào)用“帶參數(shù)之第32頁運(yùn)行時(shí)調(diào)用methods因?yàn)閙ethodoverloading機(jī)制要求signature必須唯一,而回返類型并非signature的一個(gè)成份。換句話說,只要指定了method名稱和參數(shù)列,就一定指出了一個(gè)獨(dú)一無二的method。第32頁運(yùn)行時(shí)調(diào)用methods因?yàn)閙ethodoverl第33頁運(yùn)行時(shí)調(diào)用methods第33頁運(yùn)行時(shí)調(diào)用methods第34頁運(yùn)行時(shí)變更fields內(nèi)容與先前兩個(gè)動(dòng)作相比,“變更field內(nèi)容”輕松多了,因?yàn)樗恍枰獏?shù)和自變量。首先調(diào)用Class的getField()并指定field名稱。獲得特定的Fieldobject之后便可直接調(diào)用Field的get()和set(),第34頁運(yùn)行時(shí)變更fields內(nèi)容與先前兩個(gè)動(dòng)作相比,“變更第35頁運(yùn)行時(shí)變更fields內(nèi)容第35頁運(yùn)行時(shí)變更fields內(nèi)容第36頁目錄Java反射機(jī)制代理模式第36頁目錄Java反射機(jī)制第37頁代理模式代理模式的作用是:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。在某些情況下,一個(gè)客戶不想或者不能直接引用另一個(gè)對(duì)象,而代理對(duì)象可以在客戶端和目標(biāo)對(duì)象之間起到中介的作用第37頁代理模式代理模式的作用是:為其他對(duì)象提供一種代理以控第38頁代理模式代理模式一般涉及到的角色有抽象角色:聲明真實(shí)對(duì)象和代理對(duì)象的共同接口代理角色:代理對(duì)象角色內(nèi)部含有對(duì)真實(shí)對(duì)象的引用,從而可以操作真實(shí)對(duì)象,同時(shí)代理對(duì)象提供與真實(shí)對(duì)象相同的接口以便在任何時(shí)刻都能代替真實(shí)對(duì)象。同時(shí),代理對(duì)象可以在執(zhí)行真實(shí)對(duì)象操作時(shí),附加其他的操作,相當(dāng)于對(duì)真實(shí)對(duì)象進(jìn)行封裝真實(shí)角色:代理角色所代表的真實(shí)對(duì)象,是我們最終要引用的對(duì)象第38頁代理模式代理模式一般涉及到的角色有第39頁代理模式參見程序Subject.java參見程序RealSubject.java參見程序ProxySubject.java參見程序Client.java第39頁代理模式參見程序Subject.java第40頁代理模式由以上代碼可以看出,客戶實(shí)際需要調(diào)用的是RealSubject類的request()方法,現(xiàn)在用ProxySubject來代理

RealSubject類,同樣達(dá)到目的,同時(shí)還封裝了其他方法(preRequest(),postRequest()),可以處理一些其他問題。

另外,如果要按照上述的方法使用代理模式,那么真實(shí)角色必須是事先已經(jīng)存在的,并將其作為代理對(duì)象的內(nèi)部屬性。但是實(shí)際使用時(shí),一個(gè)真實(shí)角色必須對(duì)應(yīng)一個(gè)代理角色,如果大量使用會(huì)導(dǎo)致類的急劇膨脹;此外,如果事先并不知道真實(shí)角色,該如何使用代理呢?這個(gè)問題可以通過Java的動(dòng)態(tài)代理類來解決第40頁代理模式由以上代碼可以看出,客戶實(shí)際需要調(diào)用的是Re第41頁動(dòng)態(tài)代理類Java動(dòng)態(tài)代理類位于java.lang.reflect包下,一般主要涉及到以下兩個(gè)類:(1)InterfaceInvocationHandler:該接口中僅定義了一個(gè)方法publicobjectinvoke(Objectobj,Methodmethod,Object[]args)在實(shí)際使用時(shí),第一個(gè)參數(shù)obj一般是指代理類,method是被代理的方法,如上例中的request(),args為該方法的參數(shù)數(shù)組。這個(gè)抽象方法在代理類中動(dòng)態(tài)實(shí)現(xiàn)。(2)Proxy:該類即為動(dòng)態(tài)代理類,作用類似于上例中的ProxySubject,其中主要包含以下內(nèi)容第41頁動(dòng)態(tài)代理類Java動(dòng)態(tài)代理類位于java.lang第42頁動(dòng)態(tài)代理類protectedProxy(InvocationHandlerh):構(gòu)造函數(shù),用于給內(nèi)部的h賦值。staticClassgetProxyClass(ClassLoaderloader,Class[]interfaces):獲得一個(gè)代理類,其中l(wèi)oader是類裝載器,interfaces是真實(shí)類所擁有的全部接口的數(shù)組。staticObjectnewProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh):返回代理類的一個(gè)實(shí)例,返回后的代理類可以當(dāng)作被代理類使用(可使用被代理類的在Subject接口中聲明過的方法)第42頁動(dòng)態(tài)代理類protectedProxy(Invo第43頁動(dòng)態(tài)代理類所謂DynamicProxy是這樣一種class:它是在運(yùn)行時(shí)生成的class,在生成它時(shí)你必須提供一組interface給它,然后該class就宣稱它實(shí)現(xiàn)了這些interface。你當(dāng)然可以把該class的實(shí)例當(dāng)作這些interface中的任何一個(gè)來用。當(dāng)然,這個(gè)DynamicProxy其實(shí)就是一個(gè)Proxy,它不會(huì)替你作實(shí)質(zhì)性的工作,在生成它的實(shí)例時(shí)你必須提供一個(gè)handler,由它接管實(shí)際的工作第43頁動(dòng)態(tài)代理類所謂DynamicProxy是這樣一種c第44頁動(dòng)態(tài)代理類在使用動(dòng)態(tài)代理類時(shí),我們必須實(shí)現(xiàn)InvocationHandler接口參見程序Subject.java參見程序RealSubject.java參見程序DynamicSubject.java參見程序Client.java第44頁動(dòng)態(tài)代理類在使用動(dòng)態(tài)代理類時(shí),我們必須實(shí)現(xiàn)Invoc第45頁動(dòng)態(tài)代理類通過這種方式,被代理的對(duì)象(RealSubject)可以在運(yùn)行時(shí)動(dòng)態(tài)改變,需要控制的接口(Subject接口)可以在運(yùn)行時(shí)改變,控制的方式(DynamicSubject類)也可以動(dòng)態(tài)改變,從而實(shí)現(xiàn)了非常靈活的動(dòng)態(tài)代理關(guān)系第45頁動(dòng)態(tài)代理類通過這種方式,被代理的對(duì)象(RealSub第46頁動(dòng)態(tài)代理動(dòng)態(tài)代理是指客戶通過代理類來調(diào)用其它對(duì)象的方法動(dòng)態(tài)代理使用場(chǎng)合:調(diào)試遠(yuǎn)程方法調(diào)用(RMI)第46頁動(dòng)態(tài)代理動(dòng)態(tài)代理是指客戶通過代理類來調(diào)用其它對(duì)象的方第47頁動(dòng)態(tài)代理客戶代理對(duì)象接口代理接口第47頁動(dòng)態(tài)代理客戶接口代理接口第48頁動(dòng)態(tài)代理步驟1.創(chuàng)建一個(gè)實(shí)現(xiàn)接口InvocationHandler的類,它必須實(shí)現(xiàn)invoke方法2.創(chuàng)建被代理的類以及接口3.通過Proxy的靜態(tài)方法newProxyInstance(ClassLoaderloader,Class[]interfaces,InvocationHandlerh)創(chuàng)建一個(gè)代理4.通過代理調(diào)用方法第48頁動(dòng)態(tài)代理步驟1.創(chuàng)建一個(gè)實(shí)現(xiàn)接口Invocation第49頁程序?qū)嵺`參見程序VectorProxy.java參見程序Foo.java參見程序FooImpl.java參見程序FooImpl2.java參見程序CommonInvocationHandler.java參見程序Demo.java第49頁程序?qū)嵺`參見程序VectorProxy.javaJava反射機(jī)制與動(dòng)態(tài)代理版權(quán)歸浪曦視頻在線所有Java反射機(jī)制與動(dòng)態(tài)代理版權(quán)歸浪曦視第51頁概述本課程主要講述Java反射機(jī)制與設(shè)計(jì)模式之一:代理模式的原理與應(yīng)用同時(shí)詳細(xì)講述了Java對(duì)代理模式的支持以及Java中動(dòng)態(tài)代理的原理,應(yīng)用與實(shí)踐本課程要求大家對(duì)Java泛型知識(shí)有所了解,因?yàn)槌绦虼a中大量使用了泛型相關(guān)知識(shí),對(duì)于不熟悉該部分內(nèi)容的讀者,我會(huì)在下次課程中對(duì)JDK5.0中的新特性進(jìn)行講解第2頁概述本課程主要講述Java反射機(jī)制與設(shè)計(jì)模式第52頁目錄Java反射機(jī)制代理模式第3頁目錄Java反射機(jī)制第53頁Java語言的反射機(jī)制在Java運(yùn)行時(shí)環(huán)境中,對(duì)于任意一個(gè)類,能否知道這個(gè)類有哪些屬性和方法?對(duì)于任意一個(gè)對(duì)象,能否調(diào)用它的任意一個(gè)方法?答案是肯定的。這種動(dòng)態(tài)獲取類的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能來自于Java語言的反射(Reflection)機(jī)制。Java反射機(jī)制主要提供了以下功能第4頁Java語言的反射機(jī)制在Java運(yùn)行時(shí)環(huán)境中,對(duì)于任第54頁Java語言的反射機(jī)制在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的類。在運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象。在運(yùn)行時(shí)判斷任意一個(gè)類所具有的成員變量和方法。在運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法第5頁Java語言的反射機(jī)制在運(yùn)行時(shí)判斷任意一個(gè)對(duì)象所屬的第55頁Java語言的反射機(jī)制Reflection是Java被視為動(dòng)態(tài)(或準(zhǔn)動(dòng)態(tài))語言的一個(gè)關(guān)鍵性質(zhì)。這個(gè)機(jī)制允許程序在運(yùn)行時(shí)透過ReflectionAPIs取得任何一個(gè)已知名稱的class的內(nèi)部信息,包括其modifiers(諸如public,static等等)、superclass(例如Object)、實(shí)現(xiàn)之interfaces(例如Serializable),也包括fields和methods的所有信息,并可于運(yùn)行時(shí)改變fields內(nèi)容或調(diào)用methods第6頁Java語言的反射機(jī)制Reflection是Jav第56頁Java語言的反射機(jī)制一般而言,開發(fā)者社群說到動(dòng)態(tài)語言,大致認(rèn)同的一個(gè)定義是:“程序運(yùn)行時(shí),允許改變程序結(jié)構(gòu)或變量類型,這種語言稱為動(dòng)態(tài)語言”。從這個(gè)觀點(diǎn)看,Perl,Python,Ruby是動(dòng)態(tài)語言,C++,Java,C#不是動(dòng)態(tài)語言第7頁Java語言的反射機(jī)制一般而言,開發(fā)者社群說到動(dòng)態(tài)語第57頁Java語言的反射機(jī)制盡管在這樣的定義與分類下Java不是動(dòng)態(tài)語言,它卻有著一個(gè)非常突出的動(dòng)態(tài)相關(guān)機(jī)制:Reflection。這個(gè)字的意思是“反射、映象、倒影”,用在Java身上指的是我們可以于運(yùn)行時(shí)加載、探知、使用編譯期間完全未知的classes。換句話說,Java程序可以加載一個(gè)運(yùn)行時(shí)才得知名稱的class,獲悉其完整構(gòu)造(但不包括methods定義),并生成其對(duì)象實(shí)體、或?qū)ζ鋐ields設(shè)值、或喚起其methods。這種“看透class”的能力(theabilityoftheprogramtoexamineitself)被稱為introspection(內(nèi)省、內(nèi)觀、反省)。Reflection和introspection是常被并提的兩個(gè)術(shù)語第8頁Java語言的反射機(jī)制盡管在這樣的定義與分類下Jav第58頁JavaReflectionAPI簡介在JDK中,主要由以下類來實(shí)現(xiàn)Java反射機(jī)制,這些類都位于java.lang.reflect包中Class類:代表一個(gè)類。Field類:代表類的成員變量(成員變量也稱為類的屬性)。Method類:代表類的方法。Constructor類:代表類的構(gòu)造方法。Array類:提供了動(dòng)態(tài)創(chuàng)建數(shù)組,以及訪問數(shù)組的元素的靜態(tài)方法第9頁JavaReflectionAPI簡介在JDK中第59頁JavaReflectionAPI簡介例程DumpMethods類演示了ReflectionAPI的基本作用,它讀取命令行參數(shù)指定的類名,然后打印這個(gè)類所具有的方法信息第10頁JavaReflectionAPI簡介例程Du第60頁JavaReflectionAPI簡介例程ReflectTester類進(jìn)一步演示了ReflectionAPI的基本使用方法。ReflectTester類有一個(gè)copy(Objectobject)方法,這個(gè)方法能夠創(chuàng)建一個(gè)和參數(shù)object同樣類型的對(duì)象,然后把object對(duì)象中的所有屬性拷貝到新建的對(duì)象中,并將它返回這個(gè)例子只能復(fù)制簡單的JavaBean,假定JavaBean的每個(gè)屬性都有public類型的getXXX()和setXXX()方法。第11頁JavaReflectionAPI簡介例程Re第61頁JavaReflectionAPI簡介ReflectTester類的copy(Objectobject)方法依次執(zhí)行以下步驟(1)獲得對(duì)象的類型:ClassclassType=object.getClass();System.out.println("Class:"+classType.getName());第12頁JavaReflectionAPI簡介Refl第62頁JavaReflectionAPI簡介在java.lang.Object類中定義了getClass()方法,因此對(duì)于任意一個(gè)Java對(duì)象,都可以通過此方法獲得對(duì)象的類型。Class類是ReflectionAPI中的核心類,它有以下方法getName():獲得類的完整名字。getFields():獲得類的public類型的屬性。getDeclaredFields():獲得類的所有屬性。getMethods():獲得類的public類型的方法。getDeclaredMethods():獲得類的所有方法。第13頁JavaReflectionAPI簡介在jav第63頁JavaReflectionAPI簡介getMethod(Stringname,Class[]parameterTypes):獲得類的特定方法,name參數(shù)指定方法的名字,parameterTypes參數(shù)指定方法的參數(shù)類型。getConstructors():獲得類的public類型的構(gòu)造方法。getConstructor(Class[]parameterTypes):獲得類的特定構(gòu)造方法,parameterTypes參數(shù)指定構(gòu)造方法的參數(shù)類型。newInstance():通過類的不帶參數(shù)的構(gòu)造方法創(chuàng)建這個(gè)類的一個(gè)對(duì)象。第14頁JavaReflectionAPI簡介getM第64頁JavaReflectionAPI簡介(2)通過默認(rèn)構(gòu)造方法創(chuàng)建一個(gè)新對(duì)象:ObjectobjectCopy=classType.getConstructor(newClass[]{}).newInstance(newObject[]{});以上代碼先調(diào)用Class類的getConstructor()方法獲得一個(gè)Constructor對(duì)象,它代表默認(rèn)的構(gòu)造方法,然后調(diào)用Constructor對(duì)象的newInstance()方法構(gòu)造一個(gè)實(shí)例。第15頁JavaReflectionAPI簡介(2)通第65頁JavaReflectionAPI簡介(3)獲得對(duì)象的所有屬性:Fieldfields[]=classType.getDeclaredFields();Class類的getDeclaredFields()方法返回類的所有屬性,包括public、protected、默認(rèn)和private訪問級(jí)別的屬性第16頁JavaReflectionAPI簡介(3)獲第66頁JavaReflectionAPI簡介(4)獲得每個(gè)屬性相應(yīng)的getXXX()和setXXX()方法,然后執(zhí)行這些方法,把原來對(duì)象的屬性拷貝到新的對(duì)象中第17頁JavaReflectionAPI簡介(4)獲第67頁JavaReflectionAPI簡介在例程InvokeTester類的main()方法中,運(yùn)用反射機(jī)制調(diào)用一個(gè)InvokeTester對(duì)象的add()和echo()方法第18頁JavaReflectionAPI簡介在例程I第68頁JavaReflectionAPI簡介add()方法的兩個(gè)參數(shù)為int類型,獲得表示add()方法的Method對(duì)象的代碼如下:MethodaddMethod=classType.getMethod("add",newClass[]{int.class,int.class});Method類的invoke(Objectobj,Objectargs[])方法接收的參數(shù)必須為對(duì)象,如果參數(shù)為基本類型數(shù)據(jù),必須轉(zhuǎn)換為相應(yīng)的包裝類型的對(duì)象。invoke()方法的返回值總是對(duì)象,如果實(shí)際被調(diào)用的方法的返回類型是基本類型數(shù)據(jù),那么invoke()方法會(huì)把它轉(zhuǎn)換為相應(yīng)的包裝類型的對(duì)象,再將其返回第19頁JavaReflectionAPI簡介add(第69頁JavaReflectionAPI簡介在本例中,盡管InvokeTester類的add()方法的兩個(gè)參數(shù)以及返回值都是int類型,調(diào)用addMethod對(duì)象的invoke()方法時(shí),只能傳遞Integer類型的參數(shù),并且invoke()方法的返回類型也是Integer類型,Integer類是int基本類型的包裝類:Objectresult=addMethod.invoke(invokeTester,newObject[]{newInteger(100),newInteger(200)});System.out.println((Integer)result);//result為Integer類型第20頁JavaReflectionAPI簡介在本例中第70頁JavaReflectionAPI簡介java.lang.Array類提供了動(dòng)態(tài)創(chuàng)建和訪問數(shù)組元素的各種靜態(tài)方法。例程ArrayTester1類的main()方法創(chuàng)建了一個(gè)長度為10的字符串?dāng)?shù)組,接著把索引位置為5的元素設(shè)為“hello”,然后再讀取索引位置為5的元素的值第21頁JavaReflectionAPI簡介java第71頁JavaReflectionAPI簡介例程ArrayTester2類的main()方法創(chuàng)建了一個(gè)5x10x15的整型數(shù)組,并把索引位置為[3][5][10]的元素的值為設(shè)37第22頁JavaReflectionAPI簡介例程Ar第72頁“Class” class眾所周知Java有個(gè)Objectclass,是所有Javaclasses的繼承根源,其內(nèi)聲明了數(shù)個(gè)應(yīng)該在所有Javaclass中被改寫的methods:hashCode()、equals()、clone()、toString()、getClass()等。其中g(shù)etClass()返回一個(gè)Classobject。第23頁“Class” class眾所周知Java有個(gè)O第73頁“Class” classClassclass十分特殊。它和一般classes一樣繼承自O(shè)bject,其實(shí)體用以表達(dá)Java程序運(yùn)行時(shí)的classes和interfaces,也用來表達(dá)enum、array、primitiveJavatypes(boolean,byte,char,short,int,long,float,double)以及關(guān)鍵詞void。當(dāng)一個(gè)class被加載,或當(dāng)加載器(classloader)的defineClass()被JVM調(diào)用,JVM便自動(dòng)產(chǎn)生一個(gè)Classobject。如果您想借由“修改Java標(biāo)準(zhǔn)庫源碼”來觀察Classobject的實(shí)際生成時(shí)機(jī)(例如在Class的constructor內(nèi)添加一個(gè)println()),不能夠!因?yàn)镃lass并沒有publicconstructor第24頁“Class” classClassclass第74頁“Class” classClass是Reflection起源。針對(duì)任何您想探勘的class,唯有先為它產(chǎn)生一個(gè)Classobject,接下來才能經(jīng)由后者喚起為數(shù)十多個(gè)的ReflectionAPIs第25頁“Class” classClass是Refle第75頁“Class”object的取得途徑Java允許我們從多種途徑為一個(gè)class生成對(duì)應(yīng)的Classobject第26頁“Class”object的取得途徑Java允許我第76頁“Class”object的取得途徑第27頁“Class”object的取得途徑第77頁運(yùn)行時(shí)生成instances欲生成對(duì)象實(shí)體,在Reflection動(dòng)態(tài)機(jī)制中有兩種作法,一個(gè)針對(duì)“無自變量ctor”,一個(gè)針對(duì)“帶參數(shù)ctor”。如果欲調(diào)用的是“帶參數(shù)ctor“就比較麻煩些,不再調(diào)用Class的newInstance(),而是調(diào)用Constructor的newInstance()。首先準(zhǔn)備一個(gè)Class[]做為ctor的參數(shù)類型(本例指定為一個(gè)double和一個(gè)int),然后以此為自變量調(diào)用getConstructor(),獲得一個(gè)專屬ctor。接下來再準(zhǔn)備一個(gè)Object[]做為ctor實(shí)參值(本例指定3.14159和125),調(diào)用上述專屬ctor的newInstance()。第28頁運(yùn)行時(shí)生成instances欲生成對(duì)象實(shí)體,在Ref第78頁運(yùn)行時(shí)生成instances動(dòng)態(tài)生成“Classobject所對(duì)應(yīng)之class”的對(duì)象實(shí)體;無自變量。第29頁運(yùn)行時(shí)生成instances動(dòng)態(tài)生成“Classo第79頁運(yùn)行時(shí)生成instances第30頁運(yùn)行時(shí)生成instances第80頁運(yùn)行時(shí)調(diào)用methods這個(gè)動(dòng)作和上述調(diào)用“帶參數(shù)之ctor”相當(dāng)類似。首先準(zhǔn)備一個(gè)Class[]做為參數(shù)類型(本例指定其中一個(gè)是String,另一個(gè)是Hashtable),然后以此為自變量調(diào)用getMethod(),獲得特定的Methodobject。接下來準(zhǔn)備一個(gè)Object[]放置自變量,然后調(diào)用上述所得之特定Methodobject的invoke()。為什么獲得Methodobject時(shí)不需指定回返類型?第31頁運(yùn)行時(shí)調(diào)用methods這個(gè)動(dòng)作和上述調(diào)用“帶參數(shù)之第81頁運(yùn)行時(shí)調(diào)用methods因?yàn)閙ethodoverloading機(jī)制要求signature必須唯一,而回返類型并非signature的一個(gè)成份。換句話說,只要指定了method名稱和參數(shù)列,就一定指出了一個(gè)獨(dú)一無二的method。第32頁運(yùn)行時(shí)調(diào)用methods因?yàn)閙ethodoverl第82頁運(yùn)行時(shí)調(diào)用methods第33頁運(yùn)行時(shí)調(diào)用methods第83頁運(yùn)行時(shí)變更fields內(nèi)容與先前兩個(gè)動(dòng)作相比,“變更field內(nèi)容”輕松多了,因?yàn)樗恍枰獏?shù)和自變量。首先調(diào)用Class的getField()并指定field名稱。獲得特定的Fieldobject之后便可直接調(diào)用Field的get()和set(),第34頁運(yùn)行時(shí)變更fields內(nèi)容與先前兩個(gè)動(dòng)作相比,“變更第84頁運(yùn)行時(shí)變更fields內(nèi)容第35頁運(yùn)行時(shí)變更fields內(nèi)容第85頁目錄Java反射機(jī)制代理模式第36頁目錄Java反射機(jī)制第86頁代理模式代理模式的作用是:為其他對(duì)象提供一種代理以控制對(duì)這個(gè)對(duì)象的訪問。在某些情況下,一個(gè)客戶不想或者不能直接引用另一個(gè)對(duì)象,而代理對(duì)象可以在客戶端和目標(biāo)對(duì)象之間起到中介的作用第37頁代理模式代理模式的作用是:為其他對(duì)象提供一種代理以控第87頁代理模式代理模式一般涉及到的角色有抽象角色:聲明真實(shí)對(duì)象和代理對(duì)象的共同接口代理角色:代理對(duì)象角色內(nèi)部含有對(duì)真實(shí)對(duì)象的引用,從而可以操作真實(shí)對(duì)象,同時(shí)代理對(duì)象提供與真實(shí)對(duì)象相同的接口以便在任何時(shí)刻都能代替真實(shí)對(duì)象。同時(shí),代理對(duì)象可以在執(zhí)行真實(shí)對(duì)象操作時(shí),附加其他的操作,相當(dāng)于對(duì)真實(shí)對(duì)象進(jìn)行封裝真實(shí)角色:代理角色所代表的真實(shí)對(duì)象,是我們最終要引用的對(duì)象第38頁代理模式代理模式一般涉及到的角色有第88頁代理模式參見程序Subject.java參見程序RealSubject.java參見程序ProxySubject.java參見程序Client.java第39頁代理模式參見程序Subject.java第89頁代理模式由以上代碼可以看出,客戶實(shí)際需要調(diào)用的是RealSubject類的request()方法,現(xiàn)在用ProxySubject來代理

RealSubject類,同樣達(dá)到目的,同時(shí)還封裝了其他方法(preRequest(),postRequest()),可以處理一些其他問題。

另外,如果要按照上述的方法使用代理模式,那么真實(shí)角色必須是事先已經(jīng)存在的,并將其作為代理對(duì)象的內(nèi)部屬性。但是實(shí)際使用時(shí),一個(gè)真實(shí)角色

溫馨提示

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

評(píng)論

0/150

提交評(píng)論