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
.
Two overloaded methods require two method bodies (implementations). A functional interface must be an interface that can be fully implemented with a single method body, which can then be implemented using Lambda syntax or Method Reference syntax. "which one you are trying to reference from the lambda".
The compiler does not consider the return type while differentiating the overloaded method. But you cannot declare two methods with the same signature and different return types. It will throw a compile-time error. If both methods have the same parameter types, but different return types, then it is not possible.
48. How do compiler differentiate overloaded methods from duplicate methods? Compiler uses method signature to check whether the method is overloaded or duplicated. Duplicate methods will have same method signatures i.e. same name, same number of arguments and same types of arguments.
No, you cannot overload a method based on different return type but same argument type and number in java. same name.
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) ... ?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With