【问题标题】:Why this Java lambda expression parameter has an error?为什么这个 Java lambda 表达式参数有错误?
【发布时间】:2016-07-22 19:50:04
【问题描述】:

这是一个使用解释器 GOF 模式的算术表达式求值器,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 编译器会删除泛型类型,但是,¿有办法吗?

更新:

这是表达式界面。

public interface Expression<T> {

     public <T> T interpret(IContext context);

}

【问题讨论】:

  • 您能否将Expression 的代码包含在内?我建议使用您的 IDE 将代码重构为匿名类,修复代码以便编译并重构回来。
  • 最后一个问题:不要使用原始类型。 e1 和 e2 应该是 Expression 类型,而不是 Expression。对于错误: BiFunction 接受两个参数,并返回一个结果。您的 lambda 接受 3 个参数:a、b 和结果。
  • @JB Nizet 谢谢,我可以在 lambda 上仅使用 a 和 b 来修复错误,但是对于最后一个问题,我将 e1 和 e2 更改为 Expression 并且我仍然需要强制转换。
  • public &lt;T&gt; T interpret(IContext context){ 应该是public T interpret(IContext context){
  • 是的,它可以工作,我不必投射。谢谢。

标签: java generics lambda functional-programming


【解决方案1】:

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

在表达式接口上:

public interface Expression<T> {

       public T interpret(IContext<T> context);

}

这个错误是因为我参数化了解释方法,这允许该方法返回任何对象。我记得编译器输出错误“T#2 is different from type T#1” T#2 is the generic parameter on translate method and T#1 is the generic type on the class BinaryOp.

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

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

public T interpret(IContext context);

public T interpret(IContext<T> context);

【讨论】:

  • 是的,昨天测试我的代码时,我必须修复一些错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-17
  • 1970-01-01
  • 2022-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多