java反射機(jī)制上課講義_第1頁
java反射機(jī)制上課講義_第2頁
java反射機(jī)制上課講義_第3頁
java反射機(jī)制上課講義_第4頁
java反射機(jī)制上課講義_第5頁
已閱讀5頁,還剩26頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、Good is good, but better carries it.精益求精,善益求善。java反射機(jī)制-Java的反射機(jī)制是Java特性之一,反射機(jī)制是構(gòu)建框架技術(shù)的基礎(chǔ)所在。靈活掌握J(rèn)ava反射機(jī)制,對(duì)大家以后學(xué)習(xí)框架技術(shù)有很大的幫助。那么什么是Java的反射呢?大家都知道,要讓Java程序能夠運(yùn)行,那么就得讓Java類要被Java虛擬機(jī)加載。Java類如果不被Java虛擬機(jī)加載,是不能正常運(yùn)行的?,F(xiàn)在我們運(yùn)行的所有的程序都是在編譯期的時(shí)候就已經(jīng)知道了你所需要的那個(gè)類的已經(jīng)被加載了。Java的反射機(jī)制是在編譯并不確定是哪個(gè)類被加載了,而是在程序運(yùn)行的時(shí)候才加載、探知、自審。使用在編譯期

2、并不知道的類。這樣的特點(diǎn)就是反射。那么Java反射有什么作用呢?假如我們有兩個(gè)程序員,一個(gè)程序員在寫程序的時(shí)候,需要使用第二個(gè)程序員所寫的類,但第二個(gè)程序員并沒完成他所寫的類。那么第一個(gè)程序員的代碼能否通過編譯呢?這是不能通過編譯的。利用Java反射的機(jī)制,就可以讓第一個(gè)程序員在沒有得到第二個(gè)程序員所寫的類的時(shí)候,來完成自身代碼的編譯。Java的反射機(jī)制它知道類的基本結(jié)構(gòu),這種對(duì)Java類結(jié)構(gòu)探知的能力,我們稱為Java類的“自審”。大家都用過Jcreator和eclipse。當(dāng)我們構(gòu)建出一個(gè)對(duì)象的時(shí)候,去調(diào)用該對(duì)象的方法和屬性的時(shí)候。一按點(diǎn),編譯工具就會(huì)自動(dòng)的把該對(duì)象能夠使用的所有的方法和屬

3、性全部都列出來,供用戶進(jìn)行選擇。這就是利用了Java反射的原理,是對(duì)我們創(chuàng)建對(duì)象的探知、自審。Class類要正確使用Java反射機(jī)制就得使用java.lang.Class這個(gè)類。它是Java反射機(jī)制的起源。當(dāng)一個(gè)類被加載以后,Java虛擬機(jī)就會(huì)自動(dòng)產(chǎn)生一個(gè)Class對(duì)象。通過這個(gè)Class對(duì)象我們就能獲得加載到虛擬機(jī)當(dāng)中這個(gè)Class對(duì)象對(duì)應(yīng)的方法、成員以及構(gòu)造方法的聲明和定義等信息。反射API反射API用于反應(yīng)在當(dāng)前Java虛擬機(jī)中的類、接口或者對(duì)象信息功能獲取一個(gè)對(duì)象的類信息.獲取一個(gè)類的訪問修飾符、成員、方法、構(gòu)造方法以及超類的信息.檢獲屬于一個(gè)接口的常量和方法聲明.創(chuàng)建一個(gè)直到程序運(yùn)行

4、期間才知道名字的類的實(shí)例.獲取并設(shè)置一個(gè)對(duì)象的成員,甚至這個(gè)成員的名字是在程序運(yùn)行期間才知道.檢測(cè)一個(gè)在運(yùn)行期間才知道名字的對(duì)象的方法利用Java反射機(jī)制我們可以很靈活的對(duì)已經(jīng)加載到Java虛擬機(jī)當(dāng)中的類信息進(jìn)行檢測(cè)。當(dāng)然這種檢測(cè)在對(duì)運(yùn)行的性能上會(huì)有些減弱,所以什么時(shí)候使用反射,就要靠業(yè)務(wù)的需求、大小,以及經(jīng)驗(yàn)的積累來決定。那么如何利用反射API在運(yùn)行的時(shí)候知道一個(gè)類的信息呢?代碼示例:importjava.lang.reflect.Field;importjava.lang.reflect.Method;importjavax.swing.JOptionPane;/*本類用于測(cè)試反射API,

5、利用用戶輸入類的全路徑,*找到該類所有的成員方法和成員屬性*/publicclassMyTest/*構(gòu)造方法*/publicMyTest()StringclassInfo=JOptionPane.showInputDialog(null,輸入類全路徑);/要求用戶輸入類的全路徑tryClasscla=Class.forName(classInfo);/根據(jù)類的全路徑進(jìn)行類加載,返回該類的Class對(duì)象Methodmethod=cla.getDeclaredMethods();/利用得到的Class對(duì)象的自審,返回方法對(duì)象集合for(Methodme:method)/遍歷該類方法的集合Syste

6、m.out.println(me.toString();/打印方法信息System.out.println(*);Fieldfield=cla.getDeclaredFields();/利用得到的Class對(duì)象的自審,返回屬性對(duì)象集合for(Fieldme:field)/遍歷該類屬性的集合System.out.println(me.toString();/打印屬性信息catch(ClassNotFoundExceptione)e.printStackTrace();publicstaticvoidmain(Stringargs)newMyTest();運(yùn)行的時(shí)候,我們輸入javax.swing

7、.JFrame,那么運(yùn)行結(jié)果如下:publicvoidjavax.swing.JFrame.remove(java.awt.Component)publicvoidjavax.swing.JFrame.update(java.awt.Graphics)*publicstaticfinalintjavax.swing.JFrame.EXIT_ON_CLOSEprivateintjavax.swing.JFrame.defaultCloseOperation大家可以發(fā)現(xiàn),類的全路徑是在程序運(yùn)行的時(shí)候,由用戶輸入的。所以虛擬機(jī)事先并不知道所要加載類的信息,這就是利用反射機(jī)制來對(duì)用戶輸入的類全路徑來對(duì)

8、類自身的一個(gè)自審。從而探知該類所擁有的方法和屬性。通過上面代碼,大家可以知道編譯工具為什么能夠一按點(diǎn)就能列出用戶當(dāng)前對(duì)象的屬性和方法了。它是先獲得用戶輸入對(duì)象的字符串,然后利用反射原理來對(duì)這樣的類進(jìn)行自審,從而列出該類的方法和屬性。使用反射機(jī)制的步驟:導(dǎo)入java.lang.relfect包遵循三個(gè)步驟第一步是獲得你想操作的類的java.lang.Class對(duì)象第二步是調(diào)用諸如getDeclaredMethods的方法第三步使用反射API來操作這些信息獲得Class對(duì)象的方法如果一個(gè)類的實(shí)例已經(jīng)得到,你可以使用【Classc=對(duì)象名.getClass();】例:TextFieldt=newTe

9、xtField();Classc=t.getClass();Classs=c.getSuperclass();如果你在編譯期知道類的名字,你可以使用如下的方法Classc=java.awt.Button.class;或者Classc=Integer.TYPE;如果類名在編譯期不知道,但是在運(yùn)行期可以獲得,你可以使用下面的方法Classc=Class.forName(strg);這樣獲得Class類對(duì)象的方法,其實(shí)是利用反射API把指定字符串的類加載到內(nèi)存中,所以也叫類加載器加載方法。這樣的話,它會(huì)把該類的靜態(tài)方法和靜態(tài)屬性,以及靜態(tài)代碼全部加載到內(nèi)存中。但這時(shí)候,對(duì)象還沒有產(chǎn)生。所以為什么靜態(tài)

10、方法不能訪問非靜態(tài)屬性和方法。因?yàn)殪o態(tài)方法和屬性產(chǎn)生的時(shí)機(jī)在非靜態(tài)屬性和方法之前。代碼示例:packagecom;publicclassMyTestpublicstaticvoidmain(Stringargs)TestOneone=null;tryClasscla=Class.forName(com.TestOne);/進(jìn)行com.TestOne類加載,返回一個(gè)Class對(duì)象System.out.println(*);one=(TestOne)cla.newInstance();/產(chǎn)生這個(gè)Class類對(duì)象的一個(gè)實(shí)例,調(diào)用該類無參的構(gòu)造方法,作用等同于newTestOne()catch(Exc

11、eptione)e.printStackTrace();TestOnetwo=newTestOne();System.out.println(one.getClass()=two.getClass();/比較兩個(gè)TestOne對(duì)象的Class對(duì)象是否是同一個(gè)對(duì)象,在這里結(jié)果是true。說明如果兩個(gè)對(duì)象的類型相同,那么它們會(huì)有相同的Class對(duì)象classTestOnestaticSystem.out.println(靜態(tài)代碼塊運(yùn)行);TestOne()System.out.println(構(gòu)造方法);以上代碼過行的結(jié)果是:靜態(tài)代碼塊運(yùn)行*構(gòu)造方法構(gòu)造方法代碼分析:在進(jìn)行Class.forNam

12、e(com.TestOne)的時(shí)候,實(shí)際上是對(duì)com.TestOne進(jìn)行類加載,這時(shí)候,會(huì)把靜態(tài)屬性、方法以及靜態(tài)代碼塊都加載到內(nèi)存中。所以這時(shí)候會(huì)打印出靜態(tài)代碼塊運(yùn)行。但這時(shí)候,對(duì)象卻還沒有產(chǎn)生。所以構(gòu)造方法這幾個(gè)字不會(huì)打印。當(dāng)執(zhí)行cla.newInstance()的時(shí)候,就是利用反射機(jī)制將Class對(duì)象生成一個(gè)該類的一個(gè)實(shí)例。這時(shí)候?qū)ο缶彤a(chǎn)生了。所以打印構(gòu)造方法。當(dāng)執(zhí)行到TestOnetwo=newTestOne()語句時(shí),又生成了一個(gè)對(duì)象。但這時(shí)候類已經(jīng)加載完畢,靜態(tài)的東西已經(jīng)加載到內(nèi)存中,而靜態(tài)代碼塊只執(zhí)行一次,所以不用再去加載類,所以只會(huì)打印構(gòu)造方法,而靜態(tài)代碼塊運(yùn)行不會(huì)打印。反射機(jī)

13、制不但可以例出該類對(duì)象所擁有的方法和屬性,還可以獲得該類的構(gòu)造方法及通過構(gòu)造方法獲得實(shí)例。也可以動(dòng)態(tài)的調(diào)用這個(gè)實(shí)例的成員方法。代碼示例:packagereflect;importjava.lang.reflect.Constructor;/*本類測(cè)試反射獲得類的構(gòu)造器對(duì)象,*并通過類構(gòu)造器對(duì)象生成該類的實(shí)例*/publicclassConstructorTestpublicstaticvoidmain(Stringargs)try/獲得指定字符串類對(duì)象Classcla=Class.forName(reflect.Tests);/設(shè)置Class對(duì)象數(shù)組,用于指定構(gòu)造方法類型Classcl=new

14、Classint.class,int.class;/獲得Constructor構(gòu)造器對(duì)象。并指定構(gòu)造方法類型Constructorcon=cla.getConstructor(cl);/給傳入?yún)?shù)賦初值Objectx=newInteger(33),newInteger(67);/得到實(shí)例Objectobj=con.newInstance(x);catch(Exceptione)e.printStackTrace();classTestspublicTests(intx,inty)System.out.println(x+y);運(yùn)行的結(jié)果是”3367”。說明我們已經(jīng)生成了Tests這個(gè)類的一個(gè)對(duì)

15、象。同樣,也可以通過反射模式,來執(zhí)行Java類的方法代碼示例:packagereflect;importjava.lang.reflect.Method;/*本類測(cè)試反射獲得類的方法對(duì)象,*并通過類對(duì)象和類方法對(duì)象,運(yùn)行該方法*/publicclassMethodTestpublicstaticvoidmain(Stringargs)try/獲得窗體類的Class對(duì)象Classcla=Class.forName(javax.swing.JFrame);/生成窗體類的實(shí)例Objectobj=cla.newInstance();/獲得窗體類的setSize方法對(duì)象,并指定該方法參數(shù)類型為int,i

16、ntMethodmethodSize=cla.getMethod(setSize,newClassint.class,int.class);/*執(zhí)行setSize()方法,并傳入一個(gè)Object數(shù)組對(duì)象,*作為該方法參數(shù),等同于窗體對(duì)象.setSize(300,300);*/methodSize.invoke(obj,newObjectnewInteger(300),newInteger(300);/獲得窗體類的setSize方法對(duì)象,并指定該方法參數(shù)類型為booleanMethodmethodVisible=cla.getMethod(setVisible,newClassboolean.c

17、lass);/*執(zhí)行setVisible()方法,并傳入一個(gè)Object數(shù)組對(duì)象,*作為該方法參數(shù)。等同于窗體對(duì)象.setVisible(true);*/methodVisible.invoke(obj,newObjectnewBoolean(true);catch(Exceptione)e.printStackTrace();反射技術(shù)大量用于Java設(shè)計(jì)模式和框架技術(shù),最常見的設(shè)計(jì)模式就是工廠模式(Factory)和單例模式(Singleton)。單例模式(Singleton)這個(gè)模式主要作用是保證在Java應(yīng)用程序中,一個(gè)類Class只有一個(gè)實(shí)例存在。在很多操作中,比如建立目錄數(shù)據(jù)庫連接都

18、需要這樣的單線程操作。這樣做就是為了節(jié)省內(nèi)存空間,保證我們所訪問到的都是同一個(gè)對(duì)象。單例模式要求保證唯一,那么怎么樣才能保證唯一性呢?對(duì)了,這就是靜態(tài)變量。單例模式有以下兩種形式:第一種形式:packagereflect;publicclassSingleton/*注意這是private私有的構(gòu)造方法,只供內(nèi)部調(diào)用*外部不能通過new的方式來生成該類的實(shí)例*/privateSingleton()/*在自己內(nèi)部定義自己一個(gè)實(shí)例,是不是很奇怪?*定義一個(gè)靜態(tài)的實(shí)例,保證其唯一性*/privatestaticSingletoninstance=newSingleton();/這里提供了一個(gè)供外部訪問

19、本class的靜態(tài)方法,可以直接訪問publicstaticSingletongetInstance()returninstance;/*測(cè)試單例模式*/classSingRunpublicstaticvoidmain(Stringargs)/這樣的調(diào)用不被允許,因?yàn)闃?gòu)造方法是私有的。/Singletonx=newSingleton();/得到一個(gè)Singleton類實(shí)例Singletonx=Singleton.getInstance();/得到另一個(gè)Singleton類實(shí)例Singletony=Singleton.getInstance();/比較x和y的地址,結(jié)果為true。說明兩次獲得的

20、是同一個(gè)對(duì)象System.out.println(x=y);第二種形式:publicclassSingleton/先申明該類靜態(tài)對(duì)象privatestaticSingletoninstance=null;/創(chuàng)建一個(gè)靜態(tài)訪問器,獲得該類實(shí)例。加上同步,表示防止兩個(gè)線程同時(shí)進(jìn)行對(duì)象的創(chuàng)建publicstaticsynchronizedSingletongetInstance()/如果為空,則生成一個(gè)該類實(shí)例if(instance=null)instance=newSingleton();returninstance;工廠模式(Factory)工廠模式是我們最常用的模式了,著名的Jive論壇,就大量

21、使用了工廠模式,工廠模式在Java程序系統(tǒng)可以說是隨處可見。為什么工廠模式是如此常用?是因?yàn)楣S模式利用Java反射機(jī)制和Java多態(tài)的特性可以讓我們的程序更加具有靈活性。用工廠模式進(jìn)行大型項(xiàng)目的開發(fā),可以很好的進(jìn)行項(xiàng)目并行開發(fā)。就是一個(gè)程序員和另一個(gè)程序員可以同時(shí)去書寫代碼,而不是一個(gè)程序員等到另一個(gè)程序員寫完以后再去書寫代碼。其中的粘合劑就是接口和配置文件。之前說利用接口可以將調(diào)用和實(shí)現(xiàn)相分離。那么這是怎么樣去實(shí)現(xiàn)的呢?工廠模式可以為我們解答。我們先來回顧一下軟件的生命周期,分析、設(shè)計(jì)、編碼、調(diào)試與測(cè)試。其中分析就是指需求分析,就是知道這個(gè)軟件要做成什么樣子,要實(shí)現(xiàn)什么樣的功能。功能知道了

22、,這時(shí)就要設(shè)計(jì)了。設(shè)計(jì)的時(shí)候要考慮到怎么樣高效的實(shí)現(xiàn)這個(gè)項(xiàng)目,如果讓一個(gè)項(xiàng)目團(tuán)隊(duì)并行開發(fā)。這時(shí)候,通常先設(shè)計(jì)接口,把接口給實(shí)現(xiàn)接口的程序員和調(diào)用接口的程序員,在編碼的時(shí)候,兩個(gè)程序員可以互不影響的實(shí)現(xiàn)相應(yīng)的功能,最后通過配置文件進(jìn)行整合。代碼示例:/*定義接口*/interfaceInterfaceTestpublicvoidgetName();/定義獲得名字的方法接口有了,那么得到這個(gè)接口,進(jìn)行實(shí)現(xiàn)編碼的程序員應(yīng)該怎么做呢?對(duì)了,實(shí)現(xiàn)這個(gè)接口,重寫其中定義的方法接口實(shí)現(xiàn)方:/*第一個(gè)程序員書寫的,實(shí)現(xiàn)這個(gè)接口的類*/classTest1implementsInterfaceTest/*根據(jù)業(yè)

23、務(wù),重寫方法*/publicvoidgetName()System.out.println(test1);/*第二個(gè)程序員書寫的,實(shí)現(xiàn)這個(gè)接口的類*/classTest2implementsInterfaceTest/*根據(jù)業(yè)務(wù),重寫方法*/publicvoidgetName()System.out.println(test2);大家可以發(fā)現(xiàn),當(dāng)接口定義好了以后,不但可以規(guī)范代碼,而且可以讓程序員有條不紊的進(jìn)行功能的實(shí)現(xiàn)。實(shí)現(xiàn)接口的程序員根本不用去管,這個(gè)類要被誰去調(diào)用。那么怎么能獲得這些程序員定義的對(duì)象呢?在工廠模式里,單獨(dú)定義一個(gè)工廠類來實(shí)現(xiàn)對(duì)象的生產(chǎn),注意這里返回的接口對(duì)象。工廠類,生產(chǎn)

24、接口對(duì)象:/*本類為工廠類,用于生成接口對(duì)象*/classFactory/創(chuàng)建私有的靜態(tài)的Properties對(duì)象privatestaticPropertiespro=newProperties();/靜態(tài)代碼塊statictry/加載配置文件pro.load(newFileInputStream(file.txt);catch(Exceptione)e.printStackTrace();/*單例模式,保證該類只有一個(gè)對(duì)象*/privatestaticFactoryfactory=newFactory();privateFactory()publicstaticFactorygetFacto

25、ry()returnfactory;/*本方法為公有方法,用于生產(chǎn)接口對(duì)象*returnInterfaceTest接口對(duì)象*/publicInterfaceTestgetInterface()InterfaceTestinterfaceTest=null;/定義接口對(duì)象try/根據(jù)鍵,獲得值,這里的值是類的全路徑StringclassInfo=pro.getProperty(test);/利用反射,生成Class對(duì)象Classc=Class.forName(classInfo);/獲得該Class對(duì)象的實(shí)例Objectobj=c.newInstance();/將Object對(duì)象強(qiáng)轉(zhuǎn)為接口對(duì)象interfaceTest=(InterfaceTest)obj;cat

溫馨提示

  • 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)論