1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
|
Passing lambdas to an overloaded method may be ambiguous if two overloads have
parameters that are functional interfaces with equivalent methods.
Prefer to avoid ambiguous overloads, and consider renaming one of the methods.
For example `Function<String, Integer>` and `IntFunction<String>` are both
compatible with the lambda `x -> x.hashCode()`.
```java
void f(Function<String, Integer> x) {}
void f(IntFunction<String> x) {}
```
```
error: reference to f is ambiguous
f(x -> x.hashCode());
^
both method f(Function<String,Integer>) in Test and method f(IntFunction<String>) in Test match
```
To avoid the ambiguity, callers will have to use an explicit cast:
```java
f((IntFunction<String>) x -> x.hashCode());
f((Function<String, Integer>) x -> x.hashCode());
```
## Expression-bodied lambdas
The situation is more complicated with expression-bodied lambdas. Consider:
```java
void doIt(Function<String, String> f);
void doIt(Consumer<String> c);
```
[JLS 15.12.2.1](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.2.1)
says that lambdas whose body is a statement expression are compatible with
functional interfaces whose function type is void-returning _or_ value
returning:
> A lambda expression (§15.27) is potentially compatible with a functional
> interface type (§9.8) if all of the following are true:
>
> * The arity of the target type's function type is the same as the arity of
> the lambda expression.
>
> * If the target type's function type has a void return, then the lambda body
> is either a statement expression (§14.8) or a void-compatible block
> (§15.27.2).
>
> * If the target type's function type has a (non-void) return type, then the
> lambda body is either an expression or a value-compatible block
> (§15.27.2).
So, if you have:
```java
doIt(x -> System.gc());
```
it's an implicitly typed statement-expression-bodied lambda that's compatible
with both overloads.
Any of the following disambiguate the overloads:
```
doIt((String x) -> x.toString()); // explicitly typed, calls f(Function)
doIt(x -> (x.toString())); // non-statement expression body, calls f(Function)
doIt(x -> {x.toString();}); // statement body, calls f(Consumer)
```
|