I have the following available methods in a Utils
class:
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;
});
}
And in a method of myClass
I have:
withTx(g -> anotherMethod(g));
The second piece of code has a compilation error:
The method withTx(Function<OrientGraph, Object>) is ambiguous for the type myClass
I guess this comes from the compiler, which is not able to determine if the lambda is a Consumer
or a Function
. Is there a noble way to disambiguate this situation?
Whatever the method anotherMethod
returns (void
, Object
, anything), I don't want to use this return value.
One solution is to do:
withTx(g -> { anotherMethod(g); });
But I wanted to know if there was something better, because this triggers SonarLint
.
From the "Effective Java" by Joshua Bloch:
Do not provide a method with multiple overloadings that take different functional interfaces in the same argument position if it could create a possible ambiguity in the client.
The easiest way to avoid this problem is not to write overloadings that take different functional interfaces in the same argument position.
One more possible solution could be to use a different names for these two methods:
<U> U withTxFunction(Function<OrientGraph, U> fc);
void withTxConsumer(Consumer<OrientGraph> consumer);
A good example of this approach one can find in the Java API
itself, for example in the IntStream
interface:
mapToDouble(IntToDoubleFunction mapper);
mapToLong(IntToLongFunction mapper);
Update:
I'd like to add a clarification of why does the compiler complain? That is because...
The lambda g -> anotherMethod(g)
can be assigned to both Function<T, R>
and 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) { ... }
So, when you write withTx(g -> anotherMethod(g))
, you get the "Ambiguous method call" error, the compiler fails to find out which of the overloaded method should be used:
withTx(function) OR withTx(consumer) ... ?