序言

      在學(xué)習(xí)java基礎(chǔ)時(shí),由于學(xué)的不扎實(shí),講的實(shí)用性不強(qiáng),就覺得沒用,很多重要的知識(shí)就那樣一筆帶過了,像這個(gè)馬上要講的反射機(jī)制一樣,當(dāng)時(shí)學(xué)的時(shí)候就忽略了,到后來學(xué)習(xí)的知識(shí)中,很多東西動(dòng)不動(dòng)就用反射,所以回過頭來把這個(gè)給重新補(bǔ)一下,自己欠下的債,遲早是要還的。

                                      ---WH

一、什么是反射?

    在運(yùn)行狀態(tài)中,對(duì)于任意一個(gè)類,都能夠獲取到這個(gè)類的所有屬性和方法,對(duì)于任意一個(gè)對(duì)象,都能夠調(diào)用它的任意一個(gè)方法和屬性(包括私有的方法和屬性),這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能就稱為java語言的反射機(jī)制。通俗點(diǎn)講,通過反射,該類對(duì)我們來說是完全透明的,想要獲取任何東西都可以。

    想要使用反射機(jī)制,就必須要先獲取到該類的字節(jié)碼文件對(duì)象(.class),通過字節(jié)碼文件對(duì)象,就能夠通過該類中的方法獲取到我們想要的所有信息(方法,屬性,類名,父類名,實(shí)現(xiàn)的所有接口等等),每一個(gè)類對(duì)應(yīng)著一個(gè)字節(jié)碼文件也就對(duì)應(yīng)著一個(gè)Class類型的對(duì)象,也就是字節(jié)碼文件對(duì)象。

    獲取字節(jié)碼文件對(duì)象的三種方式。

       1、Class clazz1 = Class.forName("全限定類名");  //通過Class類中的靜態(tài)方法forName,直接獲取到一個(gè)類的字節(jié)碼文件對(duì)象,此時(shí)該類還是源文件階段,并沒有變?yōu)樽止?jié)碼文件。

       2、Class clazz2  = Person.class;    //當(dāng)類被加載成.class文件時(shí),此時(shí)Person類變成了.class,在獲取該字節(jié)碼文件對(duì)象,也就是獲取自己, 該類處于字節(jié)碼階段。

       3、Class clazz3 = p.getClass();    //通過類的實(shí)例獲取該類的字節(jié)碼文件對(duì)象,該類處于創(chuàng)建對(duì)象階段 

 

    有了字節(jié)碼文件對(duì)象才能獲得類中所有的信息,我們?cè)谑褂梅瓷浍@取信息時(shí),也要考慮使用上面哪種方式獲取字節(jié)碼對(duì)象合理,視不同情況而定。下面介紹Class類的功能。

 

二、反射機(jī)制能夠獲取哪些信息?Class類的API詳解。

    2.1、通過字節(jié)碼對(duì)象創(chuàng)建實(shí)例對(duì)象

         seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

    2.2、獲取指定構(gòu)造器方法。constructor 如果沒有無參構(gòu)造,只有有參構(gòu)造如何創(chuàng)建實(shí)例呢?看下面

         seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

      總結(jié)上面創(chuàng)建實(shí)例對(duì)象:Class類的newInstance()方法是使用該類無參的構(gòu)造函數(shù)創(chuàng)建對(duì)象, 如果一個(gè)類沒有無參的構(gòu)造函數(shù), 就不能這樣創(chuàng)建了,可以調(diào)用Class類的                             getConstructor(String.class,int.class)方法獲取一個(gè)指定的構(gòu)造函數(shù)然后再調(diào)用Constructor類的newInstance("張三",20)方法創(chuàng)建對(duì)象

      獲取全部構(gòu)造方法  

         seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)     

 

    2.3、獲取成員變量并使用  Field對(duì)象

         獲取指定成員變量

         seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn) 

         Class.getField(String)方法可以獲取類中的指定字段(可見的), 如果是私有的可以用getDeclaedField("name")方法獲取,通過set(obj, "李四")方法可以設(shè)置指定對(duì)象上該字段的值, 如果是私有的需要先調(diào)用setAccessible(true)設(shè)置訪問權(quán)限,用獲取的指定的字段調(diào)用get(obj)可以獲取指定對(duì)象中該字段的值

        獲取全部成員變量

        seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

 

    2.4、獲得方法并使用  Method

         seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn) 

        Class.getMethod(String, Class...) 和 Class.getDeclaredMethod(String, Class...)方法可以獲取類中的指定方法,    

          如果為私有方法,則需要打開一個(gè)權(quán)限。setAccessible(true);

        用invoke(Object, Object...)可以調(diào)用該方法,

 

        跟上面同理,也能一次性獲得所有的方法

         seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn) 

               

    2.5、獲得該類的所有接口

         Class[] getInterfaces():確定此對(duì)象所表示的類或接口實(shí)現(xiàn)的接口

         返回值:接口的字節(jié)碼文件對(duì)象的數(shù)組

    2.6、獲取指定資源的輸入流

         InputStream getResourceAsStream(String name)  

         return:一個(gè) InputStream 對(duì)象;如果找不到帶有該名稱的資源,則返回 null

         參數(shù):所需資源的名稱,如果以"/"開始,則絕對(duì)資源名為"/"后面的一部分。

 

    2.7、動(dòng)態(tài)代理的概述和實(shí)現(xiàn)

       動(dòng)態(tài)代理:一種設(shè)計(jì)模式,其非常簡(jiǎn)單,很容易理解,你自己可以做這件事,但是覺得自己做非常麻煩或者不方便,所以就叫一個(gè)另一個(gè)人(代理)來幫你做這個(gè)事情,而你就不用管了,這就是動(dòng)態(tài)代理。舉個(gè)例子,買火車票叫人代買。 

       在程序運(yùn)行過程中產(chǎn)生的這個(gè)對(duì)象,而程序運(yùn)行過程中產(chǎn)生對(duì)象其實(shí)就是我們剛才反射講解的內(nèi)容,所以,動(dòng)態(tài)代理其實(shí)就是通過反射來生成一個(gè)代理

       在Java中java.lang.reflect包下提供了一個(gè)Proxy類和一個(gè)InvocationHandler接口,通過使用這個(gè)類和接口就可以生成動(dòng)態(tài)代理對(duì)象。JDK提供的代理只能針對(duì)接口做代理。我們有更強(qiáng)大的代理cglib,Proxy類中的方法創(chuàng)建動(dòng)態(tài)代理類對(duì)象 

        分三步,但是注意JDK提供的代理正能針對(duì)接口做代理,也就是下面的第二步返回的必須要是一個(gè)接口。

       1、new出代理對(duì)象,通過實(shí)現(xiàn)InvacationHandler接口,然后new出代理對(duì)象來。

       2、通過Proxy類中的靜態(tài)方法newProxyInstance,來將代理對(duì)象假裝成那個(gè)被代理的對(duì)象,也就是如果叫人幫我們代買火車票一樣,那個(gè)代理就假裝成我們自己本人

       3、執(zhí)行方法,代理成功

          將代理對(duì)象中的內(nèi)容進(jìn)行實(shí)現(xiàn)

          seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)     

          seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)   

          seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

  

        1、2、3步

          seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

        注意newProxyInstance的三個(gè)參數(shù),第一個(gè),類加載器,第二個(gè)被代理對(duì)象的接口,第三個(gè)代理對(duì)象。  

 

 

       

    2.8、還有很多方法,比如獲得類加載器,等等

       具體還需要?jiǎng)e的,就通過查看API文檔來解決。

 

 

三、反射機(jī)制的應(yīng)用實(shí)例

    3.1、利用反射,在泛型為int的arryaList集合中存放一個(gè)String類型的對(duì)象

       原理:集合中的泛型只在編譯器有效,而到了運(yùn)行期,泛型則會(huì)失效,

         seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

   3.2、利用反射,簡(jiǎn)化編寫Servlet的個(gè)數(shù)。

        什么意思呢?每當(dāng)我們寫一個(gè)功能時(shí),就需要寫一個(gè)對(duì)應(yīng)的Servlet,導(dǎo)致最后Servlet有很多,自己都看不過來,所以對(duì)其進(jìn)行了優(yōu)化,兩種方式,

        3.2.1、每次從頁面?zhèn)鬟^來一個(gè)參數(shù),method="xxx"; 然后編寫一個(gè)Servlet,獲得其參數(shù)method的值,進(jìn)行判斷,如果是add,則調(diào)用add方法,如果是delete,則調(diào)用delete方法,這樣就可以寫在一個(gè)servlet中實(shí)現(xiàn)所有的功能了。 

        seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

 

      3.2.2、利用反射

        編寫一個(gè)BaseServlet繼承HttpServlet,這是一個(gè)通用的BaseServlet。需要明白servlet的生命周期

        seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

        編寫具體實(shí)現(xiàn)的方法servlet類。

        MySerlvet001 extends BaseServlet

        seo優(yōu)化培訓(xùn),網(wǎng)絡(luò)推廣培訓(xùn),網(wǎng)絡(luò)營(yíng)銷培訓(xùn),SEM培訓(xùn),網(wǎng)絡(luò)優(yōu)化,在線營(yíng)銷培訓(xùn)

        

        解釋:需要明白servlet的生命周期,也就是service方法,因?yàn)槭莝ervlet,所以在訪問的時(shí)候,會(huì)經(jīng)過service方法,而子類MyServlet001中并沒有,所以就到父類BaseServlet中找,發(fā)現(xiàn)有,然后獲取參數(shù)即知道了需要調(diào)用什么方法,因?yàn)榉椒ǖ木帉懚荚谧宇愔校酝ㄟ^反射,獲取到子類中對(duì)應(yīng)的方法并運(yùn)行,其中需要注意的是this這個(gè)參數(shù)在BaseServlet中的用法。需要理解它。才能理解我們這個(gè)程序。

四、總結(jié)

      反射基本上就這樣講完了,其實(shí)就是對(duì)其一些api進(jìn)行講解,不懂的就查看API,重要的思想,就要在實(shí)際中遇到了才能得到更好的理解。先這樣過一遍,零零碎碎的知識(shí)?! ?/p>

http://www.cnblogs.com/whgk/p/6122036.html