java中java語言的反射機制:
java反射機制在運作狀態中,對於任意一個類別(class檔案),都能知道這個類別的所有屬性和方法;
對於任意一個對象,能夠呼叫它的任一方法與屬性:
這種動態所獲得的資訊以及動態呼叫物件的方法的動能稱為java語言的反射機制。
動態獲取類中信息,就是java反射,可以理解對類的解剖。有些應用程式是不能new物件的,但可以動態載入類別取得類別資訊。
如圖所示,就像類別是物件的描述一樣,Class類別可以對字節碼檔案(.class檔案)物件進行描述。
//早期:new時候,先根據被new的類的名稱找尋該類的字節碼文件,並加載進內存,
//並創建該字節碼文件對象,並接著創建該類字節碼檔案的對應的Person物件。
com.xidian.Person p=new com.xidian.Person();
//現在
String name="com.xidian.Person";
//尋找該文件類文件,並加載進內存,並產生Class對象。
Class clazz=Class.forName(name);
//如何產生該類別的物件呢?
Object obj=clazz.newInstance();
用反射類別載入的方式,從表面上看形式較為複雜但是可擴展性卻更強。原來需要自己在程式檔案手動中建立一個對象,
現在只用在設定檔中寫入字串,就可以建立對應的對象。
問題:使用clazz.newInstance()只能使用空參建構函數,要使用參數列表的建構子怎麼辦?
/*
* 取得指定名稱對應類別中的所體現的物件時,
* 而該物件初始化不使用空參建構子該怎麼辦?
*
* 既然是透過指定的建構子進行物件的初始化,
* 所以應該先得到到該建構子。透過字節碼檔案即可完成。
* 方法是:getConstructor(parameterTypes)
*
* 在反射中建構器、欄位、方法都是物件。
*/
String name="com.xidian.Person";
Class clazz=Class.forName(name);
//取得到指定的建構子物件
Constructor constructor=clazz.getConstructor(String.class,intint .class); //所有資料型別都可以用字節碼檔.class來描述
//透過該建構器物件的newInstance方法進行物件的初始化。
Object obj=constructor.newInstance("xiaoming",12);
取得指定欄位的值:
//對私有權限檢查。暴力訪問。
field_1.setAccessible(true);
Object obj=clazz.newInstance();
field_1.set(obj,88);
Object o=field_1.get(obj);
取得函數:
Method method=clazz.getMethod("show",null); //取得無參的方法
Object obj=clazz.newInstance();
method.in
Object obj=clazz.newInstance();
method.in );
Method method2=clazz.getMethod("paramMethod",String.class,int.class); //取得有參的方法,方法名稱、參數清單
Object obj2=clazz.newInstance();method2. invoke(obj2, "小強",89); //invoke:對帶有指定參數的指定物件呼叫由此Method 物件表示的底層方法。
反射的應用:定義一個介面:package com.xidian; public interface PCI { public void open(); public void close(); }
package com.xidian; public class SoundCard implements PCI{ public void open(){ System.out.println("sound open"); } public void close(){ System.out.println("sound close"); } }
package com.xidian; public class Mainboard { public void run(){ System.out.println("main run..."); } public void usePCI(PCI p){ if(p!=null){ p.open(); p.close(); } } }
package com.xidian; public class Test { public static void main(String[] args){ Mainboard mb=new Mainboard(); mb.run(); mb.usePCI(new SoundCard()); //如果主板需要使用其他设备,必须重新修改代码,传递一个新创建的对象,可扩展性不好。 } }
當擴充裝置的時候,只需要將裝置程式寫好,寫好設定檔,而不需要變更主程式代碼就可使用。