Reflection(反射)是被視為動态語言的關鍵,反射機制允許程式在執行期借助于Reflection API取得任何類的内部資訊,并能直接操作任意對象的内部屬性及方法。
1、 Java 反射機制提供的功能
在運作時判斷任意一個對象所屬的類。
在運作時構造任意一個類的對象。
在運作時判斷任意一個類所具有的成員變量和方法。
在運作時調用任意一個對象的成員變量和方法。
生成動态代理。
2、在Object類中定義了以下的方法,此方法将被所有子類繼承:
public final Class getClass()
以上的方法傳回值的類型是一個Class類,此類是Java反射的源頭,實際上所謂反射從程式的運作結果來看也很好了解,即:可以通過對象反射求出類的名稱。
1) 前提:若已知具體的類,通過類的class屬性擷取,該方法最為安全可靠,程式性能最高。
執行個體:Class clazz = String.class;
2) 前提:已知某個類的執行個體,調用該執行個體的getClass()方法擷取Class對象。
執行個體:Class clazz = “www.atguigu.com”.getClass();
3) 前提:已知一個類的全類名,且該類在類路徑下,可通過Class類的靜态方法forName()擷取,可能抛出
ClassNotFoundException。
執行個體:Class clazz = Class.forName(“java.lang.String”);
4)其他方式(不做要求)
ClassLoader cl = this.getClass().getClassLoader();
Class clazz4 = cl.loadClass(“類的全類名”);
當程式主動使用某個類時,如果該類還未被加載到記憶體中,則系統會通過如下三個步驟來對該類進行初始化。

2.1. 建立類的對象:調用Class對象的newInstance()方法
要 求:1)類必須有一個無參數的構造器。
2)類的構造器的通路權限需要足夠。
難道沒有無參的構造器就不能建立對象了嗎?
不是!隻要在操作的時候明确的調用類中的構造方法,并将參數傳遞進去之後,才可以執行個體化操作。步驟如下:
1)通過Class類的getDeclaredConstructor(Class … parameterTypes)
取得本類的指定形參類型的構造器
2)向構造器的形參中傳遞一個對象數組進去,裡面包含了構造器中所需的各個參數。
3)通過Constructor執行個體化對象。
有了 有了Class對象,能做什麼? 對象,能做什麼?
以上是反射機制應用最多的地方。
使用反射可以取得:
1.實作的全部接口 實作的全部接口
确定此對象所表示的類或接口實作的接口。
2.所繼承的父類 所繼承的父類
傳回表示此 Class 所表示的實體(類、接口、基本類型)的父類的 Class。
3.全部的構造器 全部的構造器
傳回此 Class 對象所表示的類的所有public構造方法。
傳回此 Class 對象表示的類聲明的所有構造方法。
Constructor類中:
取得修飾符: <code>public int getModifiers();</code>
取得方法名稱: <code>public String getName();</code>
取得參數的類型:<code>public Class<?>[] getParameterTypes();</code>
4.全部的方法 全部的方法
傳回此Class對象所表示的類或接口的全部方法。
傳回此Class對象所表示的類或接口的public的方法。
Method類中:
<code>public Class<?> getReturnType()</code>取得全部的傳回值。
<code>public Class<?>[] getParameterTypes()</code>取得全部的參數。
<code>public int getModifiers()</code>取得修飾符。
<code>public Class<?>[] getExceptionTypes()</code>取得異常資訊。
5. 全部的Field
傳回此Class對象所表示的類或接口的public的Field。
傳回此Class對象所表示的類或接口的全部Field。
lField方法中:
<code>這裡寫代碼片</code>public int getModifiers() 以整數形式傳回此Field的修飾符。
<code>public Class<?> getType()</code> 得到Field的屬性類型。
<code>public String getName()</code> 傳回Field的名稱。
6. Annotation相關 相關
7.泛型相關 泛型相關
擷取父類泛型類型:Type getGenericSuperclass()
泛型類型:ParameterizedType
擷取實際的泛型類型參數數組:
getActualTypeArguments()
8. 類所在的包 Package getPackage()
通過反射,調用類中的方法,通過Method類完成。步驟:
1.通過Class類的getMethod(String name,Class…parameterTypes)方
法取得一個Method對象,并設定此方法操作時所需要的參數類型。
2.之後使用Object invoke(Object obj, Object[] args)進行調用,并向
方法中傳遞要設定的obj對象的參數資訊。
說明:
1.Object 對應原方法的傳回值,若原方法無傳回值,此時傳回null。
2.若原方法若為靜态方法,此時形參Object obj可為null。
3.若原方法形參清單為空,則Object[] args為null。
4.若原方法聲明為private,則需要在調用此invoke()方法前,顯式調用方法對象的setAccessible(true)方法,将可通路private的方法。
在反射機制中,可以直接通過Field類操作類中的屬性,通過Field類提供的set()和get()方法就可以完成設定和取得屬性内容的操作。
public Field getField(String name) 傳回此Class對象表示的類或接口的指定的public的Field。
public Field getDeclaredField(String name)傳回此Class對象表示的類或接口的指定的Field。
在 在Field中:
public Object get(Object obj) 取得指定對象obj上此Field的屬性内容。
public void set(Object obj,Object value) 設定指定對象obj上此Field的屬性内容。
注:在類中屬性都設定為private的前提下,在使用set()和get()方法時,首先要使用Field類中的setAccessible(true)方法将需要操作的屬性設定為可以被外部通路。
public void setAccessible(true)通路私有屬性時,讓這個屬性可見。