简体   繁体   English

是否可以将算术运算符传递给java中的方法?

[英]Is it possible to pass arithmetic operators to a method in java?

Right now I'm going to have to write a method that looks like this:现在我将不得不编写一个如下所示的方法:

public String Calculate(String operator, double operand1, double operand2)
{

        if (operator.equals("+"))
        {
            return String.valueOf(operand1 + operand2);
        }
        else if (operator.equals("-"))
        {
            return String.valueOf(operand1 - operand2);
        }
        else if (operator.equals("*"))
        {
            return String.valueOf(operand1 * operand2);
        }
        else
        {
            return "error...";
        }
}

It would be nice if I could write the code more like this:如果我能像这样编写代码就好了:

public String Calculate(String Operator, Double Operand1, Double Operand2)
{
       return String.valueOf(Operand1 Operator Operand2);
}

So Operator would replace the Arithmetic Operators (+, -, *, /...)所以运算符将替换算术运算符(+、-、*、/...)

Does anyone know if something like this is possible in java?有谁知道在java中是否有可能发生这样的事情?

No, you can't do that in Java.不,你不能在 Java 中做到这一点。 The compiler needs to know what your operator is doing.编译器需要知道您的操作员在做什么。 What you could do instead is an enum:可以做的是一个枚举:

public enum Operator
{
    ADDITION("+") {
        @Override public double apply(double x1, double x2) {
            return x1 + x2;
        }
    },
    SUBTRACTION("-") {
        @Override public double apply(double x1, double x2) {
            return x1 - x2;
        }
    };
    // You'd include other operators too...

    private final String text;

    private Operator(String text) {
        this.text = text;
    }

    // Yes, enums *can* have abstract methods. This code compiles...
    public abstract double apply(double x1, double x2);

    @Override public String toString() {
        return text;
    }
}

You can then write a method like this:然后你可以写一个这样的方法:

public String calculate(Operator op, double x1, double x2)
{
    return String.valueOf(op.apply(x1, x2));
}

And call it like this:并这样称呼它:

String foo = calculate(Operator.ADDITION, 3.5, 2);
// Or just
String bar = String.valueOf(Operator.ADDITION.apply(3.5, 2));

Method arguments in Java must be expressions. Java 中的方法参数必须是表达式。 An operator by itself is not an expression.运算符本身不是表达式。 This is not possible in Java.这在 Java 中是不可能的。

You can, of course, pass objects (maybe enum constants) that represents those operators, and act accordingly, but you can't pass the operators themselves as parameters.当然,您可以传递代表这些运算符的对象(可能是enum常量),并相应地采取行动,但您不能将运算符本身作为参数传递。


Additional tips其他提示

Since you're just starting Java, it's best to ingrain these informations early on to ease your future development.由于您刚刚开始使用 Java,因此最好尽早将这些信息融入其中,以简化您未来的开发工作。

  • Method names starts with lowercase: calculate instead of Calculate方法名称以小写开头: calculate而不是Calculate
  • Variable names starts with lowercase: operator instead of Operator变量名以小写开头: operator而不是Operator
  • Double is a reference type, the box for primitive type double . Double是一种引用类型,是原始类型double的框。
    • Effective Java 2nd Edition, Item 49: Prefer primitive types to boxed primitives Effective Java 2nd Edition,Item 49:Preferprimitive types to boxed primes
  • Don't return "error..." .不要return "error..." Instead, throw new IllegalArgumentException("Invalid operator");相反, throw new IllegalArgumentException("Invalid operator");

See also也可以看看

There's only the cumbersome way of doing it with a callback interface.使用回调接口只有一种繁琐的方法。 Something like就像是

interface Operator {
    public Double do(Double x, Double y);
}

Then you implement the operators you need:然后你实现你需要的操作符:

Operator plus = new Operator() {
    public Double do(Double x, Double y) {
        return x + y;
    }
};

And your generic method takes an Operator and the two arguments:你的泛型方法需要一个 Operator 和两个参数:

public String Calculate(Operator operator, Double x, Double y) {
    return String.valueOf( operator.do(x, y) );
}

You could also use an enum instead of an interface if you only need a smaller, fixed number of operators.如果您只需要较小的固定数量的运算符,您也可以使用枚举而不是接口。

You can't pass operators directly.您不能直接传递运算符。 You could use functors .你可以使用函子

public double Calculate(BinaryFunction<Double, Double, Double> op, double Operand1, double Operand2)
{
  return (double)op.evaluate(Operand1, Operand2);
}

You can either你可以

  1. Use a functional language for JVM to implement this part of your code (clojure, scala et el), wrap lambda functions around math operators and pass those functions as parameters使用 JVM 的函数式语言来实现这部分代码(clojure、scala 等),将 lambda 函数包装在数学运算符周围并将这些函数作为参数传递

  2. Get an expression evaluator for Java like http://www.singularsys.com/jep/ (and there must be many free alternatives as well)获得一个像http://www.singularsys.com/jep/这样的 Java 表达式评估器(而且肯定有很多免费的替代品)

No this is not possible in this way.不,这是不可能的。

You will need a parser to do what you want, and this can be cumbersome.你需要一个解析器来做你想做的事情,这可能很麻烦。

You're probably asking the wrong question, since you are getting the wrong answer.你可能问错了问题,因为你得到了错误的答案。

If you are looking for a mathematical parser you might want to take a look at this project on SF: http://sourceforge.net/projects/jep/如果您正在寻找数学解析器,您可能想看看 SF 上的这个项目: http : //sourceforge.net/projects/jep/

There might be some answers in this.这里面可能有一些答案。

It would be nice, wouldn't it?会很好,不是吗? But, you just can't do that.但是,你不能那样做。 You can probably accomplish, something similar by writing your own "operators".您可能可以通过编写自己的“运算符”来完成类似的事情。

public interface Operator {
  Double calculate(Double op1, Double op2);
}

public Addition implements Operator {
  @Override
  Double calculate(Double op1, Double op2) { return op1 + op2; }
}

public class Calculator {
  private static Operator ADDITION = new Addition();
  private static Map<String,Operator> OPERATORS = new HashMap<String,Operator>();
  static {
    OPERATORS.put("+",ADDITION);
  }

  public String Calculate(String operator, Double operand1, Double operand2) {
    return String.valueOf(OPERATORS.get(operator).calculate(operand1,operand2);
  }
}

You get the picture how to extend this to many other operators ... and not only Doubles obviously.您了解如何将其扩展到许多其他运营商......显然不仅仅是双打。 The advantage of my method is that you can actualy keep your method signature of accepting a String operator.我的方法的优点是您实际上可以保留接受String运算符的方法签名。

Since the introduction of lambda expressions and functional interfaces in Java 8, you can do it more idiomatically.由于在 Java 8 中引入了lambda 表达式函数式接口,您可以更惯用地进行操作。

public static <T> T calculate(BinaryOperator<T> operator, T operand1, T operand2) {
  return operator.apply(operand1, operand2);
}

Whether you want to have these BinaryOperator s predefined (or declared somewhere as constants) is more of a stylistic choice.您是否想要预定义这些BinaryOperator s(或在某处声明为常量)更多的是一种风格选择。

Integer r1 = calculate((a, b) -> a + b, 2, 2); // 4
Integer r2 = calculate(Integer::sum, 2, 2); // 4

Operators, AFAIK, cannot be passed as a parameter in any language (at least that I've come across).运算符 AFAIK 不能作为任何语言的参数传递(至少我遇到过)。

Reason is that only values (either by copy or by references) can be passed as "values to parameters".原因是只有值(通过复制或通过引用)可以作为“参数值”传递。

And operators represent no values.运算符不代表任何值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM