天天看點

Java反射小結

一、什麼是反射?

在運作狀态中,對于任意一個類,都能夠擷取到這個類的所有屬性和方法,對于任意一個對象,都能夠調用它的任意一個方法和屬性(包括私有的方法和屬性),這種動态擷取的資訊以及動态調用對象的方法的功能就稱為java語言的反射機制。通俗點講,通過反射,該類對我們來說是完全透明的,想要擷取任何東西都可以。

想要使用反射機制,就必須要先擷取到該類的位元組碼檔案對象(.class),通過位元組碼檔案對象,就能夠通過該類中的方法擷取到我們想要的所有資訊(方法,屬性,類名,父類名,實作的所有接口等等),每一個類對應着一個位元組碼檔案也就對應着一個Class類型的對象,也就是位元組碼檔案對象。

擷取位元組碼檔案對象的三種方式。

1、Class clazz1 = Class.forName("全限定類名"); //通過Class類中的靜态方法forName,直接擷取到一個類的位元組碼檔案對象,此時該類還是源檔案階段,并沒有變為位元組碼檔案。

2、Class clazz2 = Person.class; //當類被加載成.class檔案時,此時Person類變成了.class,在擷取該位元組碼檔案對象,也就是擷取自己, 該類處于位元組碼階段。

3、Class clazz3 = p.getClass; //通過類的執行個體擷取該類的位元組碼檔案對象,該類處于建立對象階段

有了位元組碼檔案對象才能獲得類中所有的資訊,我們在使用反射擷取資訊時,也要考慮使用上面哪種方式擷取位元組碼對象合理,視不同情況而定。下面介紹Class類的功能。

二、反射機制能夠擷取哪些資訊?Class類的API詳解。

2.1、通過位元組碼對象建立執行個體對象

2.2、擷取指定構造器方法。constructor 如果沒有無參構造,隻有有參構造如何建立執行個體呢?看下面

總結上面建立執行個體對象:Class類的newInstance方法是使用該類無參的構造函數建立對象, 如果一個類沒有無參的構造函數, 就不能這樣建立了,可以調用Class類的 getConstructor(String.class,int.class)方法擷取一個指定的構造函數然後再調用Constructor類的newInstance("張三",20)方法建立對象

擷取全部構造方法

2.3、擷取成員變量并使用 Field對象

擷取指定成員變量

Class.getField(String)方法可以擷取類中的指定字段(可見的), 如果是私有的可以用getDeclaedField("name")方法擷取,通過set(obj, "李四")方法可以設定指定對象上該字段的值, 如果是私有的需要先調用setAccessible(true)設定通路權限,用擷取的指定的字段調用get(obj)可以擷取指定對象中該字段的值

擷取全部成員變量

2.4、獲得方法并使用 Method

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

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

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

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

2.5、獲得該類的所有接口

Class getInterfaces:确定此對象所表示的類或接口實作的接口

傳回值:接口的位元組碼檔案對象的數組

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

InputStream 

getResourceAsStream(String name)

return:一個 InputStream 對象;如果找不到帶有該名稱的資源,則傳回

參數:所需資源的名稱,如果以"/"開始,則絕對資源名為"/"後面的一部分。

2.7、動态代理的概述和實作

動态代理:一種設計模式,其非常簡單,很容易了解,你自己可以做這件事,但是覺得自己做非常麻煩或者不友善,是以就叫一個另一個人(代理)來幫你做這個事情,而你就不用管了,這就是動态代理。舉個例子,買火車票叫人代買。

在程式運作過程中産生的這個對象,而程式運作過程中産生對象其實就是我們剛才反射講解的内容,是以,動态代理其實就是通過反射來生成一個代理

在Java中java.lang.reflect包下提供了一個Proxy類和一個InvocationHandler接口,通過使用這個類和接口就可以生成動态代理對象。JDK提供的代理隻能針對接口做代理。我們有更強大的代理cglib,Proxy類中的方法建立動态代理類對象

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

1、new出代理對象,通過實作InvacationHandler接口,然後new出代理對象來。

2、通過Proxy類中的靜态方法newProxyInstance,來将代理對象假裝成那個被代理的對象,也就是如果叫人幫我們代買火車票一樣,那個代理就假裝成我們自己本人

3、執行方法,代理成功

将代理對象中的内容進行實作

1、2、3步

注意newProxyInstance的三個參數,第一個,類加載器,第二個被代理對象的接口,第三個代理對象。

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

具體還需要别的,就通過檢視API文檔來解決。

三、反射機制的應用執行個體

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

原理:集合中的泛型隻在編譯器有效,而到了運作期,泛型則會失效,

3.2、利用反射,簡化編寫Servlet的個數。

什麼意思呢?每當我們寫一個功能時,就需要寫一個對應的Servlet,導緻最後Servlet有很多,自己都看不過來,是以對其進行了優化,兩種方式,

3.2.1、每次從頁面傳過來一個參數,method="xxx"; 然後編寫一個Servlet,獲得其參數method的值,進行判斷,如果是add,則調用add方法,如果是delete,則調用delete方法,這樣就可以寫在一個servlet中實作所有的功能了。

3.2.2、利用反射

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

編寫具體實作的方法servlet類。

MySerlvet001 extends BaseServlet

解釋:需要明白servlet的生命周期,也就是service方法,因為是servlet,是以在通路的時候,會經過service方法,而子類MyServlet001中并沒有,是以就到父類BaseServlet中找,發現有,然後擷取參數即知道了需要調用什麼方法,因為方法的編寫都在子類中,是以通過反射,擷取到子類中對應的方法并運作,其中需要注意的是this這個參數在BaseServlet中的用法。需要了解它。才能了解我們這個程式。

四、總結

反射基本上就這樣講完了,其實就是對其一些api進行講解,不懂的就檢視API,重要的思想,就要在實際中遇到了才能得到更好的了解。先這樣過一遍,零零碎碎的知識。