为什么这个Java lambda表达式参数有错误?

时间:2016-04-03 07:44:39

标签: java generics lambda functional-programming

这是一个使用解释器GOF模式的aritmetic表达式计算器,BinaryOp是一个非终结表达式。

public class BinaryOP<T> implements Expression<T> {

    private Expression<T> e1;
    private Expression<T> e2;
    private BiFunction<Expression<T>, Expression<T>, T> f;

    public BinaryOp(Expression<T> e1, Expression<T> e2, 
            BiFunction<Expression<T>, Expression<T>, T> f){
        this.e1 = e1; this.e2 = e2; this.f = f;
    }

    @Override
    public <T> T interpret(IContext context){
        return (T)f.apply(e1, e2);
    }
}

变量是终端表达式。

public class Variable<T> implements Expression<T> {     
    private T v;

    public Variable(T v){
        this.v = v;
    }

    @Override
    public <T> T interpret(IContext context){
        return (T)context.recognize(v);
    }
}

当定义BiFunction和时,我在使用lambda时会出现错误,如果a和b的类型为表达式并且结果返回一个整数¿为什么会出现这个错误?

public class AritmeticInterpreter
{
    public static void main(String[] args) {    
    IContext<Integer> ctxArimetic = value -> value;

    BiFunction<Expression<Integer>, Expression<Integer>, Integer> sum
    //Error = incompatible types: incompatible parameter types in lambda expression                                       
                = (a, b, result) -> {
                return (Integer)a.interpret(ctxArimetic) + (Integer)b.interpret(ctxArimetic);
           };
    }
}

导致此错误的原因是,必须是返回类型的另一个表达式? 如果我将解释方法返回类型更改为表达式,我将无法像这样将两个表达式a和b相加:

(a, b) -> a + b

因为它们不是整数。

而且,这不是标题的一部分,但是,我可以摆脱对方法的演绎吗?我知道java编译器会删除泛型类型,但是,有没有办法?

更新

这是Expression界面。

public interface Expression<T> {

     public <T> T interpret(IContext context);

}

1 个答案:

答案 0 :(得分:0)

根据JB Nizet评论和example我发现我只需要在lambda中使用a和b作为参数。

这是正确的代码。

public static void main(String[] args) {

    IContext<Integer> ctxArimetic = value -> value;     

    BiFunction<Expression<Integer>, Expression<Integer>, Integer> sum
            = (a, b) -> {
        return a.interpret(ctxArimetic) + b.interpret(ctxArimetic);
    };

}

以及最后一个问题。

在BinaryOP类上我做了这个改变:

@Override
public T interpret(IContext<T> context){
        return f.apply(e1, e2);
}

并在Expression接口上:

public interface Expression<T> {

       public T interpret(IContext<T> context);

}

这个错误是因为我参数化了解释方法,这允许该方法返回任何对象。我记得编译器输出错误“T#2与类型T#1不同”T#2是通用参数&lt; T&gt;关于解释方法和T#1是类BinaryOp&lt; T&gt;上的泛型类型。

我不知道如何正确使用lambdas和泛型。

更新:修正了一些错误,我改了

public T interpret(IContext context);

public T interpret(IContext<T> context);