如何使用反射动态地通过名称调用 Java 中的方法?

javaobject oriented programmingprogramming

Java 中的反射 API 允许您使用其字符串名称动态调用任何方法。使用 java.lang.reflect API 时,您可以按名称加载类,即使在编译时无法访问它们,这要归功于反射的强大机制。它使您能够使用反射动态调用任何方法,并使您能够从类中检索所有方法,包括私有方法和公共方法。

不熟悉 Java 的人可能会觉得这个想法很奇怪。由于在编译期间没有用于调用方法的显式代码,因此 Java 可以在运行时以字符串形式提供方法名称时执行该方法。反射是一种有效的机制,可让您灵活地执行不同的任务。

使用的方法

这里使用了两个函数 -

  • 通过名称调用方法

  • 通过名称在类中定位方法并调用它

方法 1:通过名称调用方法

getDeclaredMethod() 函数可用于通过名称调用方法。它具有以下语法。

语法


Class.getDeclaredMethod("方法名称", 参数类型)

此语法中的"方法名称"表示您正在查找的方法的名称。

方法的参数类型指定它将接受的参数类型。

该函数接受调用并返回一个包含方法地址的对象。稍后将使用此对象调用该方法。invoke 方法将用于调用该方法。该方法最初是使用通过invoke函数()从getDeclaredMethod获得的Method对象来调用的。

它的语法如下:

语法


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

通过调用getDeclaredMethod()获取MethodObj使我们能够轻松地调用我们所需的选定方法。

参数param1、param2等显示应传递给方法的参数值。当方法没有参数时,您可以绕过null。

getDeclaredMethod()

该程序演示了如何使用Java中的Reflection API通过方法名称调用方法。它创建了"Tutorialspoint"类,其中包含打印消息的"printMessage"方法。在主方法中,它使用类对象获取"printMessage"的方法对象,并使用消息调用该方法。输出显示该方法已成功调用,并显示提供的消息。

算法

  • 导入必要的 Java 包。

  • 想出一个名为 Tutorialspoint 的类,其中包含一个接受 String 参数的 printMessage() 方法。

  • 想出一个 main() 方法,该方法打印一条消息并创建一个 Tutorialspoint 对象。

  • 获取 Tutorialspoint 类的 Class 对象。

  • 获取 printMessage() 方法的 Method 对象。

  • 在 Tutorialspoint 对象上调用 printMessage() 方法,并传入一个 String 参数。

  • 捕获任何 InvocationTargetException 并打印原因(如果有)。

  • 程序将打印指示成功的输出消息方法的调用。

示例


// 使用 Reflection API 通过方法名称调用方法的 Java 程序

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 使用 Reflection 允许您通过名称调用方法!");
        
        // 创建类对象以获取其详细信息
        Tutorialspoint obj = new Tutorialspoint();
        
        Class<?> classObj = obj.getClass();
        
        // 通过名称获取"printMessage"函数的方法对象
        Method printMessage = classObj.getDeclaredMethod("printMessage", String.class);
        
        try {
        // 使用此类 obj 调用函数
        // 传入类对象
        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() 方法获取有关方法参数的更多信息,以获取有关其返回类型的更多统计数据。一旦我们掌握了有关方法的参数和返回类型的重要统计数据,我们将使用调用方法之前提到的调用功能。

使用此方法,我们可以动态搜索路径并获取其信息,而无需事先知道其确切的参数。

语法


Method[] methods = Class.getDeclaredMethods()

numAdd()

该程序演示了如何使用 Java 中的 Reflection 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.");

        // 创建类对象以获取其详细信息
        Tutorialspoint obj = new Tutorialspoint();
        
        Class classObj = obj.getClass();
        
        // 获取类中的所有方法
        Method[] allMethods = classObj.getDeclaredMethods();
        
        // 循环遍历方法以查找方法 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

结论

反射可用于按名称动态调用方法。它对于调试、生成代码和扩展现有培训可能很有用。但是,谨慎使用反射非常重要,因为如果使用不当可能会有风险。


相关文章