【问题标题】:Call a class method from a java variable从 java 变量调用类方法
【发布时间】:2014-10-26 23:04:13
【问题描述】:

我对 Java 还很陌生,我在大学里学过它,但从那以后就没有真正接触过它。我正在尝试再次学习它,并且正在制作一个简单的客户端服务器游戏,但遇到了一些问题。

基本上,我要做的是让我有一个包含玩家可以执行的所有命令的类,并且我想根据他们向服务器发送的内容来调用该命令。

客户端发送“杀死怪物”等消息。

服务器应该拆分字符串并调用方法kill('monster');

我显然可以使用开关映射命令,但我想尝试反射并根据发送的字符串动态调用方法。我认为这会使我的代码更简洁一些,因为我只需要添加新方法和一个处理程序,以便在没有这样的方法时使用。

在 PHP 中这真的很简单,你可以通过说 myclass->$mymethod('a string'); 来调用函数

我已经设置了客户端和服务器,让客户端键入一个字符串并将其发送到服务器,服务器将其保存在变量消息中。

我在 Java 中尝试过的是:

String[] parts = message.split(" ", 2);
Command.class.getMethod(parts[0].toLowerCase(), String.class).invoke(parts[1].toLowerCase());

但这对我不起作用,我得到一个错误

java.lang.IllegalArgumentException: object is not an instance of declaring class

Command.java 很简单,是这样的:

public class Command {
    public Command(){

    }

    public void kill(String monster){
        System.out.println(monster + " Kills you!");
    }
}

我做错了什么。我特别不确定的一件事是getMethod()的第二个参数。

【问题讨论】:

  • 有几种方法可以完成您正在尝试做的事情。一种是从命令到调用这些命令的创建接口的显式映射。正如您所建议的,另一种方法涉及反思。但是,我会提醒您在反射方法上要小心……如果您没有仔细限制调用哪些方法(例如,使用白名单或对可以由客户端调用的方法进行必需的注释),您可能最终会无意中允许客户端调用您服务器中定义的任意方法。
  • Java 不是动态语言——没有办法简单地做到这一点。选项包括使用反射,使用方法名称作为键(开关或映射)选择的回调或实现“动作”接口的枚举,其实例是从输入中解析的。我不建议尝试对初学者实施任何这些替代方案。

标签: java reflection methods


【解决方案1】:

错误本身是因为您尝试调用的方法是 instance 方法,并且您需要该命令的实例来调用它(现在,您正在尝试调用kill 类实例上的 kill 方法——您传递的第一个参数)。详情请参阅this answerMethod.invoke() javadoc

但如果您需要在应用程序代码中进行反射,这通常意味着您没有走上正轨(至少从 OOP 的角度来看)。

在您的特定情况下,各种命令应该被建模为同一类的方法,而是作为它的实例(参见command pattern,例如,甚至strategy pattern,作为有用的例子)。

由于您只想每个命令有一个实例(并且您需要按名称找到正确的命令),因此enum 可能是这里最合适的选择:

enum Command {
    KILL {
        @Override public void execute(String arg) {
            System.out.printf("%s is dying...", arg)
        }
    },
    KISS {
        @Override public void execute(String arg) {
            System.out.printf("I'm kissing %s!", arg)
        }
    };

    public abstract void execute(String arg);
}

那么,你的代码就变得简单了:

Command.valueOf(parts[0].toUpperCase()).execute(parts[1].toLowerCase());

【讨论】:

  • 这是一个很好的回应,它不仅解决了我的问题,而且使我可以使用比我尝试做的更简单的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
  • 2019-05-19
  • 1970-01-01
  • 2016-11-19
相关资源
最近更新 更多