【问题标题】:Java reflection API and invoking a method with variable number of argumentsJava 反射 API 和调用具有可变数量参数的方法
【发布时间】:2011-12-18 09:27:58
【问题描述】:

当我使用 Java 反射 API 调用接受可变数量参数的方法时,我在尝试解决一种情况时遇到了问题。每次我尝试这样做时,都会收到“NoSuchMethodException”。

我要调用的方法声明:

public void AddShow(String movieName, String cinemaName, String... days) {
}

以及执行调用的方法的代码:

public void Exec(String command){
    try {
        String[] words = command.split(" ");
        String commandName = words[0];
        Class<? extends UserInterface> thisClass = (Class<? extends UserInterface>)getClass();
        Class<String>[] par = new Class[words.length-1];
        String[] params = new String[words.length-1];
        for(int i = 1; i< words.length; i++){
            params[i-1] = words[i];
            try {
                par[i-1] = (Class<String>) Class.forName("java.lang.String");
            } catch (ClassNotFoundException e) {
                System.out.println("If this shows up, something is siriously wrong... Waht have you done?!");
            }
        }
        Method method;
        if(par.length != 0) {
            method = thisClass.getMethod(commandName, par);
            method.invoke(new UserInterface(CinemaDb), (Object[])params);
        } else {
            method = thisClass.getMethod(commandName);
            method.invoke(new UserInterface(CinemaDb));
        }
    } catch (SecurityException e) {
        System.out.println("Security error, sry again.");
    } catch (NoSuchMethodException e) {
        System.out.println("Wrong command, try again (check the parameters)!");
    } catch (IllegalAccessException e) {
        System.out.println("You don't have access rights, try again.");
    } catch (IllegalArgumentException e) {
        System.out.println("Wrong arguments, try again.");
    } catch (InvocationTargetException e) {
        System.out.println("Invocation error, try again.");
    }
}

如果您知道如何更改我的 Exec 方法来解决此问题,我将不胜感激。

谢谢!

【问题讨论】:

  • 你的 Exec 方法应该命名为 exec,而不是 Clas.forName("java.lang.string"),你可以只做 String.class :更短更安全。
  • 我为什么要把它命名为“exec”?由于命名约定,或者您指的是其他任何东西。感谢您的提示,它使我的代码更清晰。
  • 是的,尊重 Java 命名约定。在 Java 中,方法总是以小写字母开头。

标签: java reflection methods parameter-passing invoke


【解决方案1】:

Java中的varargs是通过数组实现的,所以参数是String.class, String.class, and String[].class

【讨论】:

  • 嗯,还有其他方法吗?因为我无法确定传入的字符串参数是否是数组的一部分,或者它们是否只是普通参数......
【解决方案2】:

varargs部分编译后表示为String[],所以使用String[].class

在您的情况下,这会有点困难,因为您无法确切知道可变参数之前有多少参数。因此,如果您调用showFoo str1 str2 str3 str4,您将无法知道可变参数之前有多少个字符串参数。

所以你可以在你的命令字符串中放置一个分隔符,它会告诉解析器在哪里添加String[].class。另一种选择是简单地调用getMethods() 并仅通过其名称获取所需的方法(迭代并比较名称)。但是你将无法使用重载。

也就是说,我认为使用这种特殊格式的字符串来进行反射执行并不是一个好主意(除非它来自外部系统,但这可能是一个安全问题)

【讨论】:

  • 是的,但我使用相同的 Exec 方法来运行更多方法,所以我无法确定传入的参数是 Array 的一部分还是它们是正常参数
  • 好吧,你不能,因为情况就是这样。检查我更新的第 3 段是否有替代方案,但通常就是这样。
  • 好吧,你可能是对的,但我正在创建一个用户界面,它接受用户传递的命令,因此我决定创建一个大开关来使用我认为使用起来可能更容易和更简单的每个命令反射 API...
  • 用户是否将命令作为字符串输入,包含方法名称?他不能按按钮吗,例如
  • 它是一个命令行工具,所以不是。我试图让它尽可能简单,但我认为没有在命令中添加额外字符作为分隔符的方法。
【解决方案3】:

持有参数的Object[] 应该有两个String 参数和String[],你传递的是一个单位String[]

【讨论】:

  • 是的,但我使用相同的 Exec 方法来运行更多方法,所以我无法确定传入的参数是 Array 的一部分还是它们是正常参数
  • @Tromax 尽管如此,这就是问题所在。您需要找到一种方法来确定反射调用所需的内容。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-07
  • 2015-06-27
  • 2014-11-14
相关资源
最近更新 更多