我可以将字符串映射到java中的方法吗?
Posted
技术标签:
【中文标题】我可以将字符串映射到java中的方法吗?【英文标题】:Can I map a String to a method in java? 【发布时间】:2011-10-06 23:18:50 【问题描述】:我正在用 Java 编写表达式求值器。我希望能够添加更多运算符(我目前只有 (、)、+、-、*、/ 和 ^)。目前,我的代码如下所示:
case '+':
return a+b;
case '-':
return a-b;
case '*':
return a*b;
...
这适用于我的代码,因为我只有几个运算符。但是,如果我要添加更多运算符,代码会变得混乱。我正在寻找一种将运算符(由字符串表示)映射到方法的方法。例如,“ln”会映射到 Math.log(),“^”会映射到 Math.pow(),等等。
我该怎么做呢?如果不可行,有什么替代方案?
【问题讨论】:
查看前几天的a similar question。 【参考方案1】:除非您想使用反射,否则不可能。没有反射的解决方案可能如下所示:
public interface Operation
int apply(int... operands);
public abstract class BinaryOperation implements Operation
@Override
public int apply(int... operands)
return apply(operands[0], operands[1]);
abstract int apply(int a, int b);
Map<String, Operation> operations = new HashMap<String, Operation>()
put("+", new Operation()
@Override
public int apply(int... operands)
return operands[0] + operands[1];
);
put("-", new BinaryOperation()
@Override
public int apply(int a, int b)
return a - b;
);
;
【讨论】:
这仅在所有运算符采用相同数量的参数时才有效。不过,它比我现在拥有的要好得多。谢谢。 您可以让Operation.apply
需要可变数量的参数,或者List
的参数。
@Derek,这也可以使用enum
以类似的方式完成。
我喜欢有可变数量的参数的想法。【参考方案2】:
你可以使用模板方法。
public enum Functions
ADD()
@Override public int execute(int a, int b)
return a+b;
,
SUB()
@Override public int execute(int a, int b)
return a-b;
;
//Template method
public abstract int execute(int a, int b);
然后在字符串和枚举之间映射Map<String, Functions> functionMap
所以如果你想添加你可以做functionMap.put("+", Functions.ADD);
然后拨打functionMap.get("+").execute(a,b);
如果不同的函数采用不同数量的参数,我想你也可以使用可变参数。
public abstract int execute (Integer... inputs);
这个例子是根据Making the Most of Java 5.0: Enum Tricks和@duffymo所说的修改而来的。
【讨论】:
此解决方案的缺点是,您必须在要添加新操作时修改枚举。臭名昭著的表达问题:en.wikipedia.org/wiki/Expression_problem @Ionut G. Stan 好吧,没有人会阻止他将其定义为接口,并在启动时加载一些包含定义的文件,从中创建匿名类并将它们存储在 Hashmap 中 @Voo,我相信这基本上会将我的答案转换为@Ionuț G. Stan 的。【参考方案3】:基于上面的 Operation
建议,Map<String, Operation>
将通过查找来管理它。
【讨论】:
【参考方案4】:我认为您的设置是最佳设置,因为我想不出在 java 中轻松做到这一点的方法,尽管在像 c/c++ 这样的语言中,您可以轻松地将字符串映射到函数指针,但我认为没有等价的这在Java AFAIK中。不过 switch 语句的美妙之处在于它们实际上避免了混乱,因为在视觉上你可以很容易地看到 switch 语句的大小写,并且只需寻找你想要的适当大小写(尽管对于你创建的字符串,你需要一个巨大的 if 级联,因为 = = 运算符在 java 中未重载以进行字符串比较)。
编辑:请参阅 Ryan Stewarts 评论,他们使用 OOP 方式来做你想做的事。尽管在某些情况下这似乎比您的 switch 语句更混乱。
【讨论】:
是的,在大多数 Java 版本中,您无法打开字符串 @Andrew,当您遇到开始看起来难看的字符串时。 if (str.equals("case1")).... else if (str.equals("case2"))...以上是关于我可以将字符串映射到java中的方法吗?的主要内容,如果未能解决你的问题,请参考以下文章
我可以将行/模型映射到由 SQLAlchemy 中的枚举列(或字符串列上的逻辑)键入的字典吗?