什么';Java中最惯用的按名称动态调用函数的方法是什么?

什么';Java中最惯用的按名称动态调用函数的方法是什么?,java,dry,Java,Dry,我有一组特定的操作,我希望能够通过名称动态访问这些操作 如果我使用JavaScript,我会在字典中表示它们,操作名称作为键,操作函数作为值 然后,例如,我可以询问用户操作的名称,如果操作存在,则显示操作的结果,如果操作不存在,则显示错误消息,如下所示: var操作={ 加法:函数(a,b){返回a+b;}, 减法:函数(a,b){返回a-b;}, 乘法:函数(a,b){返回a*b;} //等等。 }; 变量a=4,b=7; var opName=prompt(“输入操作名称:”); if(操

我有一组特定的操作,我希望能够通过名称动态访问这些操作

如果我使用JavaScript,我会在字典中表示它们,操作名称作为键,操作函数作为值

然后,例如,我可以询问用户操作的名称,如果操作存在,则显示操作的结果,如果操作不存在,则显示错误消息,如下所示:

var操作={
加法:函数(a,b){返回a+b;},
减法:函数(a,b){返回a-b;},
乘法:函数(a,b){返回a*b;}
//等等。
};
变量a=4,b=7;
var opName=prompt(“输入操作名称:”);
if(操作中的opName){
警报(“结果:+操作[opName](a,b));
}否则{
警报(“操作“+opName+””不存在。”);
}
公共接口功能{
双行程(双a、双b);
}
公共类addFunction实现函数{
双行程(双a、双b){
返回a+b;
}
}
//...
映射操作=新的HashMap();
put(“add”,newaddfunction());
//...
字符串op;
双a,b;
操作.get(op).run(a,b);
公共接口功能{
双行程(双a、双b);
}
公共类addFunction实现函数{
双行程(双a、双b){
返回a+b;
}
}
//...
映射操作=新的HashMap();
put(“add”,newaddfunction());
//...
字符串op;
双a,b;
操作.get(op).run(a,b);

您可以在Java中执行相同的操作,而无需使用Java8:

public interface Operation<T,R> {
    R perform(T... args);
}

public void test() {
    Map<String, Operation> operations = new HashMap<String, Operation>() {
        {
            this.put("addition", new Operation<Integer, Integer>() {
                public Integer perform(Integer... args) {
                    return args[0] + args[1];
                }});
        }
    };

    String operation = "";
    Integer a = 1;
    Integer b = 1;
    if (operations.containsKey(operation)) {
        System.out.println("Result: " + operations.get(operation).perform(a, b));
    } else {
        System.out.println("The operation '" + operation + "' does not exist.");
    }
}
公共接口操作{
R执行(T…args);
}
公开无效测试(){
映射操作=新建HashMap(){
{
this.put(“添加”,新操作(){
公共整数执行(整数…参数){
返回参数[0]+args[1];
}});
}
};
字符串操作=”;
整数a=1;
整数b=1;
if(操作.容器(操作)){
System.out.println(“结果:+operations.get(operation.perform)(a,b));
}否则{
System.out.println(“操作“+”操作不存在。”);
}
}
如果您愿意,也可以将匿名类移动到单独的文件中

如果需要不同类型的参数,则必须使用泛型或将参数类型更改为
Object
,然后执行强制转换。不漂亮,但这是静态输入的代价


此外,如果您希望在同一映射中存储不同类型的操作,编译器将向您发出警告(使用原始
操作
),但此处没有太多操作。一种解决方法是为不同的类型制作多个映射。

您可以在Java中执行相同的操作,而无需使用Java8:

public interface Operation<T,R> {
    R perform(T... args);
}

public void test() {
    Map<String, Operation> operations = new HashMap<String, Operation>() {
        {
            this.put("addition", new Operation<Integer, Integer>() {
                public Integer perform(Integer... args) {
                    return args[0] + args[1];
                }});
        }
    };

    String operation = "";
    Integer a = 1;
    Integer b = 1;
    if (operations.containsKey(operation)) {
        System.out.println("Result: " + operations.get(operation).perform(a, b));
    } else {
        System.out.println("The operation '" + operation + "' does not exist.");
    }
}
公共接口操作{
R执行(T…args);
}
公开无效测试(){
映射操作=新建HashMap(){
{
this.put(“添加”,新操作(){
公共整数执行(整数…参数){
返回参数[0]+args[1];
}});
}
};
字符串操作=”;
整数a=1;
整数b=1;
if(操作.容器(操作)){
System.out.println(“结果:+operations.get(operation.perform)(a,b));
}否则{
System.out.println(“操作“+”操作不存在。”);
}
}
如果您愿意,也可以将匿名类移动到单独的文件中

如果需要不同类型的参数,则必须使用泛型或将参数类型更改为
Object
,然后执行强制转换。不漂亮,但这是静态输入的代价


此外,如果您希望在同一映射中存储不同类型的操作,编译器将向您发出警告(使用原始
操作
),但此处没有太多操作。一种解决方法是为不同的类型制作多个映射。

在Java 8中,使用lambdas会更整洁:

Map<String, BinaryOperator<Integer>> operators = new TreeMap<>();
operators.put("add", (n1, n2) -> n1 + n2);
operators.put("minus", (n1, n2) -> n1 - n2);

if (operators.containsKey(opName)) {
    return operators.get(opName).apply(n1, n2);
}

在使用lambdas的Java 8中,这要整洁得多:

Map<String, BinaryOperator<Integer>> operators = new TreeMap<>();
operators.put("add", (n1, n2) -> n1 + n2);
operators.put("minus", (n1, n2) -> n1 - n2);

if (operators.containsKey(opName)) {
    return operators.get(opName).apply(n1, n2);
}

您是否考虑过使用Java 8 lambdas?@anubhavashok我正在编写代码,希望能够集成到Android应用程序中,而Java 8在Android设备上不受广泛支持。您为什么要这样做?一般来说,首选的Java方法是实现一个接口并使用
Map
。1) 使用映射2)打开操作名3)使用带有每个常量覆盖的抽象方法的枚举。@PeterOlson一点也不奇怪。事实上,这与有效Java中的示例几乎完全相同。在那本书中,使用了枚举,你考虑过使用Java 8 lambdas吗?@anubhavashok我正在编写代码,希望能够集成到Android应用程序中,而Java 8在Android设备上不受广泛支持。你为什么要这样做?一般来说,首选的Java方法是实现一个接口并使用
Map
。1) 使用映射2)打开操作名3)使用带有每个常量覆盖的抽象方法的枚举。@PeterOlson一点也不奇怪。事实上,这与有效Java中的示例几乎完全相同。在那本书中,使用了枚举,就像往常一样,我不介意否决投票,但我希望有一两条评论。你有我的赞成票,它满足了我的要求,尽管我的天哪,Java太冗长了@PeterOlson冗长,但您仍然会收到我提到的编译器警告:-)尽管在Java8和Scala中它要好得多。就我个人而言,我喜欢处理大项目时的冗长,但那只是我自己。我一向不介意否决投票,但我希望能有一两条评论。你有我的赞成票,这正是我想要的,尽管我的天哪,Java太冗长了@PeterOlson冗长,正如我提到的,您仍然会收到编译器警告