Java 如何调用存储在 HashMap 中的方法?(爪哇)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4480334/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 17:55:52  来源:igfitidea点击:

How to call a method stored in a HashMap? (Java)

javahashmethodsinvoke

提问by cwhiii

I have a list of commands (i, h, t, etc) that the user will be entering on a command line/terminal Java program. I would like to store a hash of command/method pairs:

我有用户将在命令行/终端 Java 程序中输入的命令列表(i、h、t 等)。我想存储命令/方法对的散列:

'h', showHelp()
't', teleport()

So that I can have code something like:

这样我就可以有类似的代码:

HashMap cmdList = new HashMap();

cmdList.put('h', showHelp());
if(!cmdList.containsKey('h'))
    System.out.print("No such command.")
else
   cmdList.getValue('h')   // This should run showHelp().

Is this possible? If not, what is an easy way to this?

这可能吗?如果没有,有什么简单的方法可以做到这一点?

采纳答案by aioobe

With Java 8+ and Lambda expressions

使用 Java 8+ 和 Lambda 表达式

With lambdas (available in Java 8+) we can do it as follows:

使用 lambdas(在 Java 8+ 中可用),我们可以这样做:

class Test {

    public static void main(String[] args) throws Exception {
        Map<Character, Runnable> commands = new HashMap<>();

        // Populate commands map
        commands.put('h', () -> System.out.println("Help"));
        commands.put('t', () -> System.out.println("Teleport"));

        // Invoke some command
        char cmd = 't';
        commands.get(cmd).run();   // Prints "Teleport"
    }
}

In this case I was lazy and reused the Runnableinterface, but one could just as well use the Command-interface that I invented in the Java 7 version of the answer.

在这种情况下,我很懒惰并重用了Runnable接口,但也可以使用Command我在 Java 7 版本的答案中发明的-interface。

Also, there are alternatives to the () -> { ... }syntax. You could just as well have member functions for helpand teleportand use YourClass::helpresp. YourClass::teleportinstead.

此外,还有() -> { ... }语法的替代方案。您也可以为helpandteleport和使用YourClass::helpresp使用成员函数。YourClass::teleport反而。



Java 7 and below

Java 7 及以下

What you really want to do is to create an interface, named for instance Command(or reuse for instance Runnable), and let your map be of the type Map<Character, Command>. Like this:

您真正想要做的是创建一个接口,命名为 instance Command(或重用 instance Runnable),并让您的地图的类型为Map<Character, Command>。像这样:

import java.util.*;

interface Command {
    void runCommand();
}

public class Test {

    public static void main(String[] args) throws Exception {
        Map<Character, Command> methodMap = new HashMap<Character, Command>();

        methodMap.put('h', new Command() {
            public void runCommand() { System.out.println("help"); };
        });

        methodMap.put('t', new Command() {
            public void runCommand() { System.out.println("teleport"); };
        });

        char cmd = 'h';
        methodMap.get(cmd).runCommand();  // prints "Help"

        cmd = 't';
        methodMap.get(cmd).runCommand();  // prints "teleport"

    }
}

Reflection "hack"

反射“黑客”

With that said, you canactually do what you're asking for (using reflection and the Methodclass.)

话虽如此,您实际上可以做您所要求的(使用反射和Method类。)

import java.lang.reflect.*;
import java.util.*;

public class Test {

    public static void main(String[] args) throws Exception {
        Map<Character, Method> methodMap = new HashMap<Character, Method>();

        methodMap.put('h', Test.class.getMethod("showHelp"));
        methodMap.put('t', Test.class.getMethod("teleport"));

        char cmd = 'h';
        methodMap.get(cmd).invoke(null);  // prints "Help"

        cmd = 't';
        methodMap.get(cmd).invoke(null);  // prints "teleport"

    }

    public static void showHelp() {
        System.out.println("Help");
    }

    public static void teleport() {
        System.out.println("teleport");
    }
}

回答by Erich Kitzmueller

Though you could store methods through reflection, the usual way to do it is to use anonymous objects that wrap the function, i.e.

虽然您可以通过反射存储方法,但通常的方法是使用包装函数的匿名对象,即

  interface IFooBar {
    void callMe();
  }


 'h', new IFooBar(){ void callMe() { showHelp(); } }
 't', new IFooBar(){ void callMe() { teleport(); } }

 HashTable<IFooBar> myHashTable;
 ...
 myHashTable.get('h').callMe();

回答by DVD

If you are using JDK 7 you can now use methods by lambda expression just like .net.

如果您使用的是 JDK 7,您现在可以像 .net 一样通过 lambda 表达式使用方法。

If Not the best way is to make a Function Object:

如果不是,最好的方法是创建一个函数对象:

public interface Action {    void performAction(); }

Hashmap<string,Action> cmdList;

if(!cmdList.containsKey('h'))
    System.out.print("No such command.") else    cmdList.getValue('h').performAction();