| 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) |
| ``` |