Ric*_*ker 2 java reflection casting
我有一个如下所示的Command类:
public class Command {
...
private String commandName;
private Object[] commandArgs;
...
public void executeCommand() {}
}
Run Code Online (Sandbox Code Playgroud)
我还有一个Command,AuthenticateCommand的子类:
public class AuthenticateCommand extends Command {
...
@Override
public void executeCommand() {
...
}
}
Run Code Online (Sandbox Code Playgroud)
现在假设一个类Server,它有一个方法processCommand(命令命令).它接受命令param,检查commandName字段,并使用该名称将命令强制转换为Command的子类,负责实现命令逻辑.在此示例中,您可能拥有一个CommandName,其commandName为"authenticate",而command和pw存储在commandArgs数组中.processCommand()会将Command强制转换为AutheticateCommand并调用executeCommand()方法.我试图用以下内容完成此任务(commandMap只是一个将commandName映射到其实现者类名的Map):
public void processCommand(Command command) {
String commandName = command.getCommandName();
String implementorClassString = commandMap.get(commandName);
try {
Class implementorClass = Class.forName(implementorClassString);
Object implementor = implementorClass.cast(command);
Method method = implementorClass.getDeclaredMethod("executeCommand", null);
method.invoke(implementor);
} catch (ClassNotFoundException e) {
logger.error("Could not find implementor class: " + implementorClassString, e);
} catch (NoSuchMethodException e) {
logger.error("Could not find executeCommand method on implementor class: " + implementorClassString, e);
} catch (IllegalAccessException e) {
logger.error("Could not access private member/method on implementor class: " + implementorClassString, e);
} catch (InvocationTargetException e) {
logger.error("Could not invoke executeCommand method on implementor class: " + implementorClassString, e);
}
}
Run Code Online (Sandbox Code Playgroud)
对implementorClass.cast()的调用抛出了ClassCastException.它不应该以这种方式向下转发到AuthenticateCommand类吗?
UPDATE
更多背景.Server类处理的不仅仅是AuthenticateCommands.可以有任意数量的Command子类,具体取决于项目.我试图让编写客户端的人简单地传递一个只带有名称和参数的序列化Command对象.我可以强制客户端"了解"AuthenticateCommand和所有其他人,然后序列化它们并传递它们,但这似乎是次优的,因为子类之间的唯一区别是executeCommand的实现,客户端并不关心或了解.所以我只想要一种方法让客户端传递父类,并使用该父类中的数据将其强制转换为适当的子类.
我想我可以使用newInstance()代替cast而只是创建一个新对象,但这看起来很浪费.我想我也可以废除处理逻辑的子类的概念并将它们移动到方法中,然后processCommand将调用适当的方法.不过,这对我来说也很不舒服.
你为什么要施展?你只是想打电话executeCommand,而且这可以通过命令...所以只需写:
command.executeCommand();
Run Code Online (Sandbox Code Playgroud)
哪个应该编译运行.目前还不清楚地图的位置.
至于为什么演员表失败...我的猜测是该命令的ClassLoader不是此时的默认ClassLoader,因此它implementorClass是相同的类,但由不同的ClassLoader加载...这使它有所不同关于JVM的类.
编辑:我会说你的设计坏了.Command您传递的对象未正确履行其角色.一种选择是拥有一个RemoteCommand知道名称的新子类,并且在executeCommand调用其方法时,它会构建适当的子类实例.是的,这将需要建立一个类的实例.如果没有该类的实例,则无法在类上调用实例方法,并且不能使一个对象"假装"它实际上是不同类型的对象.如果AuthenticationCommand有一些额外的字段试图使用该怎么办?这些价值来自哪里?
一个更好的选择是让你的序列化/反序列化层做到这一点,所以,到时候你已经达到了这段代码,你已经得到了一个AuthenticationCommand-你可以在这个答案的顶部使用的代码.
| 归档时间: |
|
| 查看次数: |
509 次 |
| 最近记录: |