Java反射技術應用廣泛,其能夠配置:類的全限定名,方法和引數,完成物件的初始化,設定是反射某些方法。可以增強java的可配置性。
1.1 通過反射構建物件(無引數):
例如我們使用 ReflectServiceImpl 類講解這個例子
1 public class ReflectServiceImpl { 2 public void sayHello(String name){ 3 System.out.println("hello"+name); 4 } 5 }
我們通過反射的方法去構建它。
1 public ReflectServiceImpl getInstance(){ 2 ReflectServiceImpl object=null; 3 try { 4 object=(ReflectServiceImpl)Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl").newInstance(); 5 } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { 6 e.printStackTrace(); 7 } 8 return object; 9 }
其中第4行:object=(ReflectServiceImpl)Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl").newInstance();
是給類載入器註冊一個類ReflectServiceImpl的許可權定名,之後通過newInstance方法初始化一個類物件。
1.2 通過反射構建物件(類的構造器中帶有引數):
我們使用ReflectServiceImpl2這個類去理解:
1 public class ReflectServiceImpl2 { 2 private String name; 3 public ReflectServiceImpl2(String name) { 4 this.name=name; 5 } 6 public void sayHello(String name){ 7 System.out.println("hello"+name); 8 } 9 }
此時 ReflectServiceImpl2的構造器帶有引數 public ReflectServiceImpl2(String name){xxxx};
此時我們該如何利用反射生成物件呢?只需要在類載入器註冊的使用getConstructor(引數)方法。其中引數是我們構造器中的引數的型別。程式碼如下:
1 public ReflectServiceImpl2 getInstance(){ 2 ReflectServiceImpl2 object=null; 3 try { 4 object=(ReflectServiceImpl2)Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl2") 5 .getConstructor(String.class).newInstance("張三"); 6 } catch (InstantiationException | IllegalAccessException | ClassNotFoundException | InvocationTargetException |NoSuchMethodException e) { 7 e.printStackTrace(); 8 } 9 return object; 10 }
如4、5行所示:
先通過forName載入到類的載入器。然後通過getConstructor方法,它的引數可以是多個,這裡定義String.class,意為有且只有一個引數型別為String 的構建方法。通過這個方法可以對重名方法進行排除,此時再用newInstance方法生成物件,只是newInstance方法也多了一個引數“張三”而已。實際上就等於object=new ReflectServiceImpl2("張三").只是利用了反射來生成物件而已。
1.3 反射方法
在使用反射方法之前需要先獲取物件,得到了方法才能夠去反射。
我們使用 ReflectServiceImpl 類為例。
ReflectServiceImpl 類程式碼:
1 public class ReflectServiceImpl { 2 public void sayHello(String name){ 3 System.out.println("hello"+name); 4 } 5 }
呼叫方法:
1 public Object reflect(){ 2 ReflectServiceImpl object=null; 3 Object returnObj=null; 4 //反射生成物件 5 try { 6 object = (ReflectServiceImpl) Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl").newInstance(); 7 //反射生成方法並排程 8 Method method = object.getClass().getMethod("sayHello", String.class); 9 returnObj= method.invoke(object, "張三"); 10 }catch( ClassNotFoundException| NoSuchMethodException| InvocationTargetException| IllegalAccessException| InstantiationException e ) { 11 e.printStackTrace(); 12 } 13 return returnObj; 14 }
當有具體物件 object(型別為ReflectServiceImpl),而不知道具體是哪個類的時候,也可以使用object.getClass().getMethod("sayHello", String.class);來替代它,其中第一個引數是方法的名稱,第二個引數是引數型別,是一個列表,多個引數可以繼續編寫多個型別,這樣便能夠獲得反射的方法物件。反射方法時運用 method.invoke(object, "張三");呼叫的,第一個引數為object,就是確定用哪個物件呼叫方法,而“張三”是引數,這就等同於object.sayHello("張三");若存在多個引數可以寫成Method.invoke(target,obj1,obj2.obj3...),這些要根據物件的具體方法來確定。
1.4 測試
以ReflectServiceImpl為例:
1 package com.lean.reflect; 2 import java.lang.reflect.InvocationTargetException; 3 import java.lang.reflect.Method; 4 public class ReflectServiceImpl { 5 //屬性 6 private String name; 7 //預設的構造方法 8 public ReflectServiceImpl() { 9 super(); 10 } 11 //帶引數的構造方法 12 public ReflectServiceImpl(String name) { 13 this.name=name; 14 } 15 //方法 sayHelo 16 public void sayHello(String name){ 17 System.out.println("hello "+name); 18 } 19 //呼叫方法 20 public Object reflect(){ 21 ReflectServiceImpl object=null; 22 Object returnObj=null; 23 //反射生成物件 24 try { 25 object = (ReflectServiceImpl) Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl").newInstance(); 26 //反射生成方法並排程 27 Method method = object.getClass().getMethod("sayHello", String.class); 28 returnObj= method.invoke(object, "張三"); 29 }catch( ClassNotFoundException| NoSuchMethodException| InvocationTargetException| IllegalAccessException| InstantiationException e ) { 30 e.printStackTrace(); 31 } 32 return returnObj; 33 } 34 //獲取物件 35 public ReflectServiceImpl getInstance(){ 36 ReflectServiceImpl object=null; 37 try { 38 object=(ReflectServiceImpl)Class.forName("com.lean.ssm.chapter2.reflect.ReflectServiceImpl").newInstance(); 39 } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { 40 e.printStackTrace(); 41 } 42 return object; 43 } 44 //測試 45 public static void main(String[] args) { 46 ReflectServiceImpl rsl= new ReflectServiceImpl(); 47 rsl.reflect(); 48 } 49 }
效果圖: