Java中函数映射的等效实现

10 投票
7 回答
4893 浏览
提问于 2025-04-15 11:58

在Python中,如果我有几个函数想要根据输入来调用,我可以这样做:

lookup = {'function1':function1, 'function2':function2, 'function3':function3}
lookup[input]()

也就是说,我有一个字典,这个字典把函数的名字和函数本身对应起来,然后通过查这个字典来调用函数。

那么在Java中怎么做呢?

7 个回答

2

你可以使用一个叫做Map的东西,比如Map<String,Method>或者Map<String,Callable>,然后用map.get("function1").invoke(...)来调用函数。但是通常情况下,这种问题用多态的方法会更简单、更干净,而不是通过查找来解决。

16

Java没有一等公民的方法,所以你可以使用命令模式来解决这个问题...

注意:代码没有经过测试!

public interface Command 
{
    void invoke();
}

Map<String, Command> commands = new HashMap<String, Command>();
commands.put("function1", new Command() 
{
    public void invoke() { System.out.println("hello world"); }
});

commands.get("function1").invoke();
4

解决这个问题有几种方法。大部分方法已经有人提过了:

  • 命令模式 - 可以把一堆有 execute() 或 invoke() 方法的对象放在一个映射中;通过名字查找命令,然后调用这个方法。
  • 多态 - 更广泛地说,你可以在任何相关的对象集合上调用方法。
  • 最后是反射 - 你可以使用反射来获取 java.lang.Method 对象的引用。对于一组已知的类和方法,这种方式效果不错,而且一旦加载了 Method 对象,开销也不大。比如,你可以让用户在命令行中输入 Java 代码,然后实时执行。

个人来说,我会选择命令模式。命令模式和模板方法结合得很好,可以在所有命令对象上强制执行某些模式。举个例子:

public abstract class Command {
  public final Object execute(Map<String, Object> args) {
    // do permission checking here or transaction management
    Object retval = doExecute(args);
    // do logging, cleanup, caching, etc here
    return retval;
  }
  // subclasses override this to do the real work
  protected abstract Object doExecute(Map<String, Object> args);
}

我只会在需要对你无法控制设计的类进行这种映射时才使用反射,这种情况下做命令不太实际。例如,你不能通过为每个方法创建命令来在命令行中暴露 Java API。

撰写回答