从java变量调用类方法

从java变量调用类方法,java,reflection,methods,Java,Reflection,Methods,我对Java是相当陌生的,我在大学里学过它,但从那以后就没怎么接触过它。我正在尝试再次学习它,我正在制作一个简单的客户机-服务器游戏,但遇到了一些问题 基本上,我要做的是使它成为一个类,包含一个玩家可以执行的所有命令,我想根据他们发送给服务器的内容调用该命令 客户端发送诸如“杀死怪物”之类的消息 服务器应该拆分字符串并调用方法kill('monster') 显然,我可以用开关映射出命令,但我想尝试反射,并根据发送的字符串动态调用该方法。我认为这会使我的代码更简洁,因为我只需要在没有这样的方法时添

我对Java是相当陌生的,我在大学里学过它,但从那以后就没怎么接触过它。我正在尝试再次学习它,我正在制作一个简单的客户机-服务器游戏,但遇到了一些问题

基本上,我要做的是使它成为一个类,包含一个玩家可以执行的所有命令,我想根据他们发送给服务器的内容调用该命令

客户端发送诸如“杀死怪物”之类的消息

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

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

在PHP中,这真的很简单,您可以通过说myclass->$mymethod(“字符串”)来调用函数

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

我在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
java很简单,如下所示:

public class Command {
    public Command(){

    }

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

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

错误本身是因为您尝试调用的方法是实例方法,您需要该命令的实例来调用它(现在,您正在尝试调用
String
类的实例上的
kill
方法,这是您要传递的第一个参数)。有关详细信息,请参阅或

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

在您的特定情况下,各种命令不应被建模为同一类的方法,而应被建模为该类的实例(例如,请参见,甚至作为有用的示例)

由于您只希望每个命令有一个实例(并且需要按名称查找正确的命令),因此
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());

有几种方法可以完成您正在尝试的操作。一种是通过从命令到调用这些命令的创建界面的显式映射。另一种方法,正如您所建议的,涉及反射。但是,我要提醒您在反射方法上要小心…如果您不小心限制我使用的方法nvoked(例如,使用白名单或客户端可以调用的方法上的必需注释),您可能会无意中允许客户端调用服务器中定义的任意方法。Java不是动态语言-无法简单地做到这一点。选项包括使用反射、使用方法名称作为键(开关或映射)选择的回调或实现“操作”的枚举接口,其实例是从输入解析的。我不建议初学者尝试实现这些替代方案中的任何一个。这是一个非常好的响应,它不仅解决了我的问题,而且使我可以使用比我尝试使用的方法更简单的方法。