代码之家  ›  专栏  ›  技术社区  ›  Matthias Beaupère

消除接受不同函数接口的重载方法[重复]

  •  9
  • Matthias Beaupère  · 技术社区  · 6 年前

    我有以下可用的方法 Utils 班级:

    protected <U> U withTx(Function<OrientGraph, U> fc) {
        // do something with the function
    }
    
    protected void withTx(Consumer<OrientGraph> consumer) {
        withTx(g -> {
            consumer.accept(g);
            return null;
        });
    }
    

    用一种方法 myClass 我有:

    withTx(g -> anotherMethod(g));
    

    第二段代码有编译错误:

    The method withTx(Function<OrientGraph, Object>) is ambiguous for the type myClass

    我猜这来自编译器,它无法确定lambda是否是 Consumer 或A Function . 有没有一种高尚的方式来缓和这种局面?

    不管用什么方法 anotherMethod 收益( void , Object ,任何内容),我不想使用此返回值。

    一个解决方案是:

    withTx(g -> { anotherMethod(g); });
    

    但我想知道有没有更好的,因为这触发了 SonarLint .

    2 回复  |  直到 6 年前
        1
  •  8
  •   Oleksandr Pyrohov Andreas    6 年前

    “有效Java” 作者:约书亚·布洛赫:

    不要提供具有多个重载的方法 如果可以创建,则在相同参数位置中的函数接口 客户可能有歧义。

    避免此问题的最简单方法是不编写重载。 在同一个参数中使用不同的函数接口 位置。

    另一种可能的解决方案是对这两种方法使用不同的名称:

    <U> U withTxFunction(Function<OrientGraph, U> fc);
    
    void withTxConsumer(Consumer<OrientGraph> consumer);
    

    这种方法的一个很好的例子可以在 Java API 本身,例如 IntStream 接口:

    mapToDouble(IntToDoubleFunction mapper);
    
    mapToLong(IntToLongFunction mapper);
    

    更新:

    我想澄清一下为什么编译器会抱怨?那是因为…

    拉姆达 g -> anotherMethod(g) 可以同时分配给 Function<T, R> Consumer<T> :

    Function<T, R> func  = g -> anotherMethod(g);
    
    Consumer<T> consumer = g -> anotherMethod(g); // here you just ignore the return value
    
    <T> T anotherMethod(T t) { ... }
    

    所以,当你写 withTx(g -> anotherMethod(g)) ,你得到 “方法调用不明确” 错误,编译器无法找出应使用哪个重载方法:

    withTx(function) OR withTx(consumer) ... ?
    
        2
  •  2
  •   Coder-Man    6 年前

    实际上,你已经有了解决问题的方法,但是在另一个地方,因为你写了:

    withTx(g -> {
        consumer.accept(g);
        return null; // this calls the `Function` variant of `withTx`
    });
    

    但是无论如何,您有这个问题,因为您的函数的返回类型 anotherMethod() void ,编译器不知道从中选择什么, Function<OrientGraph, Void> Consumer<OrientGraph> . Consumer 它本身应该表示一个接受某些内容而不返回任何内容的函数。

    withTx(g -> { anotherMethod(g); }); 调用 消费者 显式变型。

    如果你想打电话给 Function 变体,DO: withTx(g -> { anotherMethod(g); return null; });