反射機制是java語言的一個特色,能夠實現在類中調用其他類裡的方法和屬性。這一個特點可以很方便的在自己開發的架構中使用,可以說功能是比較強大的一個特性。
先建立一個新的java工程,目錄結構如下:
Reflect類
package com.org.testReflect;public class Reflect {public String str="123456";public void print(){System.out.println("test ====================print");}public void printStr(String str){System.out.println("the param is================"+str);}public static void main(String[] args) {System.out.println("beging test main method----------------------");}}
TestRef是Reflect的一個測試類別。
一、獲得一個類中的方法和屬性的一個比較簡單的方法
1.獲得這個類的執行個體
Class ref = Class.forName("com.org.testReflect.Reflect");
Reflect obj = (Reflect)ref.newInstance();
2.獲得Reflect中的屬性和方法
通過newInstance這個方法的使用,我們相當於在new了一個Reflect這個類。即是相當於這個方法
Reflect refs=new Reflect();
所以我們想獲得這個類裡面的方法和屬性只要使用ref.就可以了。有的同學可能會問,既然可以直接的new一個類,為什麼還要費那麼大的勁,去使用Reflect個類的包名通過java的反射去獲得類的執行個體呢?很簡單,這是因為我們在一些情況下需要動態去new一個類而不是某一個特定的類,這時候java反射就派上用場了。比如,我們在寫架構的時候,可能會根據xml裡面的配置屬性去執行個體一個類的時候,由於xml裡面的屬性是變化的,所以要執行個體的類也是變化的,因此直接的new是不行的。
(1)獲得無參數的方法
obj.print();
(2)獲得帶參數的方法
obj.printStr("1234");
(3)獲得main方法
obj.main(args);
(4)獲得屬性
Reflect obj = (Reflect)ref.newInstance();System.out.println("================="+obj.str);
這個類的代碼
package com.org.testReflect;public class TestRef {public static void main(String[] args) {try {Reflect refs=new Reflect();Class ref = Class.forName("com.org.testReflect.Reflect");//Reflect.class.getName()//得到沒有參數的方法Reflect obj = (Reflect)ref.newInstance();obj.print();obj.printStr("1234");obj.main(args);System.out.println("================="+obj.str);} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InstantiationException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
執行結果如下
test ====================printthe param is================1234beging test main method----------------------=================123456
我們可以看到,完全的進入到了Reflect這個類裡面。而且得到裡面的方法和屬性,
二、反射機制的另外一種方法
上面提供了一種獲得其他類中的Method的方法,這裡我們給出另外的一種方法
1.載入要調用的類
Class ref = Class.forName(Reflect.class.getName());
2.調用方法
調用方法的時候,可以分為兩步
a.獲得要調用的方法
Method method=ref.getMethod(name, parameterTypes)
第一個參數是要調用的方法的名稱,第二個參數表示的方法中參數的類型
b.調用方法
method.invoke(obj, args)
第一個參數是class的一個執行個體,如果是null的話,表示該方法是一個靜態,第二個參數是要傳入的參數值。obj可以用下面的方法得到
Object obj = ref.newInstance();
下面分別舉幾個常用的方法的調用
(1)main方法
Method method = ref.getMethod("main", String[].class);method.invoke(null,(Object)new String[]{});
(2)無參方法
Method mf=ref.getMethod("print", null);mf.invoke(obj, null);
(3)帶參數的方法
Method m=ref.getMethod("printStr", String.class);m.invoke(obj, new String("asdf"));
運行結果
the param is================asdftest ====================printbeging test main method----------------------
三、帶建構函式的類
上面說的兩種方法都是沒有建構函式的類,若是有建構函式的話,上面的兩種方法就不再適用了。
我們開始建立一個新的java類Reflect2.java代碼如下
package com.org.testReflect;public class Reflect2 {public Reflect2(String str) {// TODO Auto-generated constructor stubSystem.out.println("constructor begining run param str is============="+str);}public void print(){System.out.println("test ====================print");}public void printStr(String str){System.out.println("the param is================"+str);}public static void main(String[] args) {System.out.println("beging test main method----------------------");}}
建立一個新的測試反射用的java類TestRef2.java
對於帶有建構函式的類,若是還是像之前兩種方那樣用
ref.newInstance();
會報錯的,有興趣的同學可以自己實驗下,看看報的錯誤是什麼。
這裡,我們可以按照下面的步驟來執行個體化這個類
1.得到構造器
Constructor<?>[] ref = Class.forName("com.org.testReflect.Reflect2").getConstructors();
2.執行個體化類
Object obj = ref[0].newInstance(new String("qaz"));
3.得到這個obj的執行個體後,就可以按照第二種進行調用了。這裡不再贅述,測試的結果如下
constructor begining run param str is=============qaztest ====================printthe param is================printString=========1234beging test main method----------------------