如何在 Java 中使用反射動態呼叫方法?


Java 中的反射 API 允許您使用其字串名稱動態呼叫任何方法。使用 java.lang.reflect API 時,即使在編譯時無法訪問類,您也可以透過名稱載入類,這要歸功於反射強大的機制。它使您能夠使用反射動態呼叫任何方法,並使您可以檢索類中的所有方法,包括私有方法和公共方法。

不熟悉 Java 的人可能會覺得這個想法很奇怪。在編譯期間沒有呼叫方法的顯式程式碼,Java 可以在執行時提供方法名稱作為字串時執行該方法。反射是一種有效的機制,使您能夠靈活地執行不同的任務。

使用的方法

這裡使用了兩個函式 -

  • 按名稱呼叫方法

  • 在類中按名稱定位方法並呼叫它

方法 1:使用其名稱呼叫方法

可以使用 getDeclaredMethod() 函式按名稱呼叫方法。它具有以下語法。

語法

Class.getDeclaredMethod("method name", parameterType)

此語法中的“方法名稱”表示您要查詢的方法的名稱。

方法的 parameterType 指定它將接受的引數型別。

該函式接受一個呼叫並返回一個包含方法地址的物件。稍後將使用此物件呼叫該方法。invoke 方法將用於呼叫該方法。最初使用從 getDeclaredMethod 獲得的 Method 物件透過使用 invoke 函式 () 呼叫該方法。

它具有以下語法 -

語法

methodObj.invoke(classObj, param1, param2...)

從呼叫 getDeclaredMethod() 獲取 MethodObj 使我們能夠輕鬆地呼叫我們想要選擇的特定方法。

引數 param1、param2 等顯示應傳遞給方法的引數值。當方法沒有引數時,您可以繞過 null。

getDeclaredMethod()

該程式演示瞭如何使用 Java 中的反射 API 按名稱呼叫方法。它建立了一個名為“Tutorialspoint”的類,其中包含一個列印訊息的“printMessage”方法。在主方法中,它使用類物件獲取“printMessage”的方法物件並使用訊息呼叫它。輸出顯示了使用提供的訊息成功呼叫該方法。

演算法

  • 匯入必要的 Java 包。

  • 建立一個名為 Tutorialspoint 的類,其中包含一個帶 String 引數的 printMessage() 方法。

  • 建立一個列印訊息並建立 Tutorialspoint 物件的 main() 方法。

  • 獲取 Tutorialspoint 類的 Class 物件。

  • 獲取 printMessage() 方法的 Method 物件。

  • 在 Tutorialspoint 物件上呼叫 printMessage() 方法,傳入一個 String 引數。

  • 捕獲任何 InvocationTargetException 並列印任何原因。

  • 程式將列印輸出訊息,指示方法已成功呼叫。

示例

// Java program for invoking method with its name with Reflection API

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

public class Tutorialspoint {
   public void printMessage(String message){
      System.out.println("you called on me with the message:" + message);
   }

   public static void main(String[] args) throws Exception{
      System.out.println("Java uses Reflection to allow you to invoke a method by name!");

      // create class object to get its details
      Tutorialspoint obj = new Tutorialspoint();

      Class<?> classObj = obj.getClass();

      // get method object for "printMessage" function by
      // name
      Method printMessage = classObj.getDeclaredMethod("printMessage", String.class);

      try {
         // invoke the function using this class obj
         // pass in the class object
         printMessage.invoke(obj, "Welcome Students");
      }
      catch (InvocationTargetException e){
         System.out.println(e.getCause());
      }
   }
}

輸出

Java uses Reflection to allow you to invoke a method by name!
you called on me with the message:Welcome Students

方法 2:在類中按名稱定位方法並呼叫它

如果我們不確定確切的方法引數,我們可以使用 getDeclaredMethods() API 來檢索類中的所有方法。此 API 返回一個 Method 物件陣列,我們可以對其進行操作。

使用迴圈迭代這些 Method 物件,並使用 getName() 方法透過名稱查詢特定方法。您可以使用 getGenericParameterTypes() 方法獲取有關方法引數的更多資訊,並使用 getGenericReturnType() 方法獲取有關其返回型別的更多資訊。一旦我們獲得了有關方法的引數和返回型別的必要資訊,我們就可以使用之前提到的 invoke 函式來呼叫該方法。

使用此方法,我們可以動態搜尋路徑並獲取其資訊,而無需事先知道其確切引數。

語法

Method[] methods = Class.getDeclaredMethods()

numAdd()

該程式演示瞭如何使用 Java 中的反射 API 按名稱查詢方法。它建立了一個名為“Tutorialspoint”的類,其中包含兩個方法:“printMessage”和“numAdd”。在主方法中,它獲取“Tutorialspoint”物件的類物件,並使用 getDeclaredMethods() 檢索所有宣告的方法。然後,它遍歷這些方法並檢查方法名稱是否為“numAdd”。如果匹配,則使用 invoke() 方法使用提供的整數引數呼叫該方法。輸出顯示了“numAdd”方法的成功呼叫,並列印了提供的數字的總和。

演算法

  • 步驟 1 - 建立一個名為“Tutorialspoint”的類,其中包含兩個方法:“printMessag”。它將接收一個字串引數並列印訊息,以及“numAdd”,它接收兩個整數引數並列印它們的總和。

  • 步驟 3 - 在“numAdd”方法中,列印兩個數字的總和。

  • 步驟 4 - 在主方法中,列印一條訊息,指示使用反射在 Java 中按名稱查詢方法。

  • 步驟 4 - 建立“Tutorialspoint”類的物件。

  • 步驟 5 - 使用 getClass() 方法獲取建立的物件的類物件。

  • 步驟 6 - 使用 getDeclaredMethods() 獲取在類中宣告的所有方法。

  • 步驟 7 - 使用 for-each 迴圈遍歷每個方法。

  • 步驟 8 - 檢查方法名稱是否等於“numAdd”。

  • 步驟 9 - 如果匹配,則使用 invoke() 方法直接使用提供的引數呼叫該方法,將物件和引數值傳遞給它。

  • 步驟 10 - 如果在方法呼叫期間發生異常,請捕獲 InvocationTargetException。

  • 步驟 11 - 程式將列印輸出訊息,指示方法已成功呼叫以及提供的數字的總和。

示例

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;

public class Tutorialspoint {
   public void printMessage(String message){
      System.out.println("you called on me with the message:" + message);
   }

   public void numAdd(int num1, int num2){
      System.out.println("total is:" + (num1 + num2));
   }

   public static void main(String[] args) throws Exception{
      System.out.println("Using Java's Reflection, discover a method by name.");

      // create class object for obtaining its details
      Tutorialspoint obj = new Tutorialspoint();

      Class classObj = obj.getClass();

      // get all methods in the class
      Method[] allMethods = classObj.getDeclaredMethods();

      // loop through the methods to look for the method numAdd()
      for (Method m : allMethods) {
         String methodName = m.getName();
         if (methodName.equals("numAdd")) {
            try {
               // invoke the method directly with its
               // parameters
               m.invoke(obj, 20, 30);
            }
            catch (InvocationTargetException e) {
            }
         }
      }
   }
}

輸出

Using Java's Reflection, discover a method by name.
total is:50

結論

反射可用於動態呼叫方法。它可能對除錯、程式碼生成和擴充套件現有培訓很有用。但是,務必謹慎使用反射,因為如果使用不當,它可能會很危險。

更新於: 2023-10-18

983 次瀏覽

開啟你的 職業生涯

透過完成課程獲得認證

開始學習
廣告