消除接受不同功能接口的重载方法的歧义

mat*_*sbe 9 java lambda java-8

我在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;
    });
}
Run Code Online (Sandbox Code Playgroud)

myClass我的方法中:

withTx(g -> anotherMethod(g));
Run Code Online (Sandbox Code Playgroud)

第二段代码有一个编译错误:

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

我想这来自编译器,它无法确定lambda是a Consumer还是a Function.是否有一种消除歧视这种情况的高尚方式?

无论方法anotherMethod返回什么(void,Object什么),我都不想使用这个返回值.

一种解决方案是:

withTx(g -> { anotherMethod(g); });
Run Code Online (Sandbox Code Playgroud)

但我想知道是否有更好的东西,因为这会触发SonarLint.

Ole*_*hov 8

来自Joshua Bloch 的"Effective Java":

如果可能在客户端中产生可能的歧义,则不要提供具有多个重载的方法,这些方法在相同的参数位置采用不同的功能接口.

避免此问题的最简单方法是不要编写在同一参数位置使用不同功能接口的重载.

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

<U> U withTxFunction(Function<OrientGraph, U> fc);

void withTxConsumer(Consumer<OrientGraph> consumer);
Run Code Online (Sandbox Code Playgroud)

可以在Java API自身中找到这种方法的一个很好的例子,例如在   IntStream界面中:

mapToDouble(IntToDoubleFunction mapper);

mapToLong(IntToLongFunction mapper);
Run Code Online (Sandbox Code Playgroud)

更新:

我想补充说明为什么编译器会抱怨?那是因为...

lambda 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) { ... }
Run Code Online (Sandbox Code Playgroud)

因此,当您编写时withTx(g -> anotherMethod(g)),您会收到"模糊方法调用"错误,编译器无法找出应该使用哪个重载方法:

withTx(function) OR withTx(consumer) ... ?
Run Code Online (Sandbox Code Playgroud)