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