java反射構建物件和方法的反射呼叫

ZYXS發表於2019-07-22

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 }

效果圖:

相關文章