开发者

Can I map a String to a method in java?

I'm writing an expression evaluator in Java. I would like the ability to add more operators (I currently have only (, ), +, -, *, /, and ^). Currently, my code looks like this:

case '+':  
return a+b;  
case '-':  
return a-b;  
case '*':  
return a*b;  
...

This works for my code because I have only a few operators. However, if I were to add more opera开发者_如何学Ctors, the code would become cluttered. I am looking for a way to map an operator (represented by a String) to a method. For example, "ln" would be mapped to Math.log(), "^" would be mapped to Math.pow(), etc.

How would I go about doing this? If it's not feasible, what are some alternatives?


Not possible unless you want to use reflection. A solution without reflection could look like this:

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;
    }
  });
}};


You could use template methods.

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);
}

Then map between string and enum with Map<String, Functions> functionMap So if you want to add you can do functionMap.put("+", Functions.ADD); Then call functionMap.get("+").execute(a,b);

I suppose you could also use varargs if different functions take different numbers of arguments. public abstract int execute (Integer... inputs);

This example is modified from Making the Most of Java 5.0: Enum Tricks and what @duffymo said.


Building on the Operation suggestion above, a Map<String, Operation> would manage it with a lookup.


I think your setup is the optimal setup as I cannot think of a way to do this easily in java, although in a language like c/c++ you could easily map strings to function pointers but I don't think there's an equivalent of this in Java AFAIK. The beauty of switch statements though is that they actually avoid the clutter because visually you can easily see what the case of the switch statement is and just look for the appropriate case that you want (although for strings you made need a giant if cascade since == operator is not overloaded in java for string comparison).

Edit: See Ryan Stewarts comment, they use OOP ways of doing exactly what you want. Although that seems more cluttered than your switch statement in some cases.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜