如何在 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 次浏览

开启你的 职业生涯

通过完成课程获得认证

开始学习
广告
© . All rights reserved.