標籤:
一、什麼是反射
反射的概念是由Smith在1982年首次提出的,主要是指程式可以訪問、檢測和修改它本身狀態或行為的一種能力。
Java反射機制是在運行狀態中,對於任意一個類,都能夠知道這個類的所有屬性和方法;對於任意一個對象,都能夠調用它的任意一個方法;這種動態擷取資訊以及動態調用對象方法的功能,稱為java語言的反射機制。
二、反射的應用
1.Spring架構:IOC(控制反轉)
2.Hibernate架構:關聯映射等
3.白盒測試
三、相關的API
1.java.lang包下
Class<T> : 表示一個正在啟動並執行java應用程式中的類和介面,是Reflection的起源。
2.java.lang.reflect包下
Field類 : 代表類的成員變數,也稱類的屬性。
Method類 : 代表類的方法。
Constructor類 : 代表類的構造方法。
Array類 : 提供了動態建立數組,以及訪問數組元素的靜態方法。
四、關於Class<T>
類是程式的一部分,每個類都有一個Class對象。換言之,每當編寫並且編譯了一個新類,就會產生一個Class對象。
Class沒有公用構造方法。Class對象是在載入類時由Java虛擬機器以及通過調用類載入器中的defineClass方法自動構造的,因此不能顯式地聲明一個Class對象。
Class是Reflection的起源。要想操縱類中的屬性和方法,都必須從擷取Class Object開始,擷取方式如下表。
擷取方式 |
說明 |
樣本 |
Object.getClass() |
擷取指定執行個體對象的Class |
List li = new ArrayList(); Class liCla = li.getClass(); |
Class.getSuperclass() |
擷取當前Class的繼承類Class |
List li = new ArrayList(); Class liCla = li.getClass(); Class suCla = liCla.getSuperclass(); |
Object.class |
.class直接擷取 |
Class liCla = ArrayList.class; |
Class.forName("類名") |
用class的靜態方法,傳入類的全稱即可 |
Class cla = Class.forName("java.util.ArrayList"); |
Primitive.TYPE |
基礎資料型別 (Elementary Data Type)的封裝類擷取Class的方式 |
Class longClass = Long.TYPE; Class inteClass = Integer.TYPE; |
五、反射的使用
建立反射操作的目標。
package reflection;public class BaseUser { private String baseId; public String getBaseId() { return baseId; } public void setBaseId(String baseId) { this.baseId = baseId; }}BaseUser類
package reflection;public class User extends BaseUser { private String id; public String name; public User() { } public User(String name) { this.name = name; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; }}User類,繼承BaseUser
package reflection;public class Reflection { public String pubField; public void test1() { System.out.println("這是一個public method!"); } public void test2(String test) { System.out.println("這是一個帶參 public method!參數為:" + test); } }Reflection類
(a)通過反射執行個體化對象
1.執行個體化無參建構函式的對象。
2.執行個體化帶參建構函式的對象。
package reflection;public class Demo { public static void main(String[] args) { Class<?> cla = User.class; try { User u1 = (User) cla.newInstance(); System.out.println("執行個體化無參建構函式的對象,方式一:" + u1); User u2 = (User) cla.getConstructor().newInstance(); System.out.println("執行個體化無參建構函式的對象,方式二:" + u2); User u3 = (User) cla.getConstructor(String.class).newInstance("有參"); System.out.println("執行個體化有參建構函式的對象:" + u3 + " name:" + u3.getName()); User u4 = new User(); System.out.println("常執行個體化對象:" + u4); } catch (Exception e) { e.printStackTrace(); } }}Demo類
(b)通過反射調用Method
package reflection;import java.lang.reflect.Method;public class RefMethodTest { public static void main(String[] args) throws Exception{ Class<?> clazz = Reflection.class; Object obj = clazz.newInstance(); System.out.println("獲得當前類所申明的指定的方法,test1():"); Method m1 = clazz.getDeclaredMethod("test1"); System.out.println("方法名為:" + m1.getName()); System.out.println("運行該方法:"); m1.invoke(obj); System.out.println("獲得當前類所聲明的指定的方法,test2():"); Method m2 = clazz.getDeclaredMethod("test2", String.class); System.out.println("方法名為:" + m2.getName()); System.out.println("運行該方法"); m2.invoke(obj, "這是參數"); }}RefMethodTest 類
(c)通過反射調用Field
package reflection;import java.lang.reflect.Field;public class RefFieldTest { public static void main(String[] args) throws Exception{ Class<?> clazz = Reflection.class; Object obj = clazz.newInstance(); System.out.println("獲得當前類以及超類指定的屬性,pubField:"); Field f = clazz.getDeclaredField("pubField"); System.out.println("屬性名稱:" + f.getName()); System.out.println("通過反射動態設定Field的值"); f.set(obj, "新的值"); System.out.println("通過反射動態擷取Field的值"); System.out.println("Field的值為:" + f.get(obj)); }}RefFieldTest
JAVA 反射機制