java反射就是讓你可以通過名稱來得到對象 ( 類,屬性,方法 ) 的技術。
例如我們可以通過類名來產生一個類的執行個體;
知道了方法名,就可以調用這個方法;知道了屬性名稱就可以訪問這個屬性的值。
我們甚至可以通過反射來設定對象私人屬性的值。
下面通過一個執行個體來說明反射的意義和用途:
public class Car { private String brand; private String color; private int maxSpeed; public String getBrand() { return brand; } public void setBrand(String brand) { this.brand = brand; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getMaxSpeed() { return maxSpeed; } public void setMaxSpeed(int maxSpeed) { this.maxSpeed = maxSpeed; } public String toString(){ return "the car is:"+ getBrand() + ", color is:" +getColor() +", maxspeed is:"+getMaxSpeed(); } public Car() { } public Car(String brand, String color, int maxSpeed) { this.brand = brand; this.color = color; this.maxSpeed = maxSpeed; } public void introduce() { System.out.println("brand:" + brand + ";color:" + color + ";maxSpeed:" + maxSpeed); }}
public class ReflectTest { public static Car initByDefaultConst() throws Throwable{ //通過類裝載器 擷取Car對象 ClassLoader loader = Thread.currentThread().getContextClassLoader(); Class<?> clazz = loader.loadClass("spring.ioc.demo1.Car"); //擷取類的預設構造器函數 並 執行個體化一個對象 效果等同 new Car(); /*Constructor<?> cons = clazz.getDeclaredConstructor((Class[])null); Car car = (Car)cons.newInstance();*/ //擷取類的帶參數的構造器函數getConstructor 必須是public的構造方法 Class pTypes[] = {String.class,String.class,int.class}; Constructor cons2 = clazz.getDeclaredConstructor(pTypes); Car car = (Car)cons2.newInstance("a","b",1); //通過反射方法設定屬性 /*Method setBrand = clazz.getMethod("setBrand", String.class); setBrand.invoke(car, "紅旗001"); Method setColor = clazz.getMethod("setColor", String.class); setColor.invoke(car, "黑色"); Method setMaxSpeed = clazz.getMethod("setMaxSpeed", int.class); setMaxSpeed.invoke(car, 200);*/ return car; } public static void main(String[] args) throws Throwable { Car car = ReflectTest.initByDefaultConst(); car.introduce(); }}
通過反射我們可以看到我們可以直接設定對象的私人屬性,
也可以通過調用屬性的set方法來給屬性賦值,
Spring架構中的ioc依賴注入轉就是大量利用了java本身的反射機制,
架構把我們手寫的代碼封裝了一下,這樣我們就可以通過spring設定檔來直接進行配置。
Java的類反射所需要的類並不多,它們分別是:Field、Constructor、Method、Class、Object,下面我將對這些類做一個簡單的說明。
Field類:提供有關類或介面的屬性的資訊,以及對它的動態存取權限。反射的欄位可能是一個類(靜態)屬性或執行個體屬性,簡單的理解可以把它看成一個封裝反射類的屬性的類。
Constructor類:提供關於類的單個構造方法的資訊以及對它的存取權限。這個類和Field類不同,Field類封裝了反射類的屬性,而Constructor類則封裝了反射類的構造方法。
Method類:提供關於類或介面上單獨某個方法的資訊。所反映的方法可能是類方法或執行個體方法(包括抽象方法)。 這個類不難理解,它是用來封裝反射類方法的一個類。
Class類:類的執行個體表示正在啟動並執行 Java 應用程式中的類和介面。枚舉是一種類,注釋是一種介面。每個數組屬於被映射為 Class 對象的一個類,所有具有相同元素類型和維數的數組都共用該 Class 對象。
對於以下三類組件中的任何一類來說 -- 建構函式、欄位和方法 -- java.lang.Class 提供四種獨立的反射調用,以不同的方式來獲得資訊。
調用都遵循一種標準格式。
用於尋找建構函式的一組反射調用:
l Constructor getConstructor(Class[] params) -- 獲得使用特殊的參數類型的公用建構函式,
l Constructor[] getConstructors() -- 獲得類的所有公用建構函式
l Constructor getDeclaredConstructor(Class[] params) -- 獲得使用特定參數類型的建構函式(與接入層級無關)
l Constructor[] getDeclaredConstructors() -- 獲得類的所有建構函式(與接入層級無關)
獲得欄位資訊的Class 反射調用不同於那些用於接入建構函式的調用,在參數類型數組中使用了欄位名:
l Field getField(String name) -- 獲得命名的公用欄位
l Field[] getFields() -- 獲得類的所有公用欄位
l Field getDeclaredField(String name) -- 獲得類聲明的命名的欄位
l Field[] getDeclaredFields() -- 獲得類聲明的所有欄位
用於獲得方法資訊函數:
l Method getMethod(String name, Class[] params) -- 使用特定的參數類型,獲得命名的公用方法
l Method[] getMethods() -- 獲得類的所有公用方法
l Method getDeclaredMethod(String name, Class[] params) -- 使用特寫的參數類型,獲得類聲明的命名的方法
l Method[] getDeclaredMethods() -- 獲得類聲明的所有方法