OK, so method overloading is-a-bad-thing™. Now that this has been settled, let's assume I actually want to overload a method like this:
static void run(Consumer<Integer> consumer) {
System.out.println("consumer");
}
static void run(Function<Integer, Integer> function) {
System.out.println("function");
}
In Java 7, I could call them easily with non-ambiguous anonymous classes as arguments:
run(new Consumer<Integer>() {
public void accept(Integer integer) {}
});
run(new Function<Integer, Integer>() {
public Integer apply(Integer o) { return 1; }
});
Now in Java 8, I'd like to call those methods with lambda expressions of course, and I can!
// Consumer
run((Integer i) -> {});
// Function
run((Integer i) -> 1);
Since the compiler should be able to infer Integer
, why don't I leave Integer
away, then?
// Consumer
run(i -> {});
// Function
run(i -> 1);
But this doesn't compile. The compiler (javac, jdk1.8.0_05) doesn't like that:
Test.java:63: error: reference to run is ambiguous
run(i -> {});
^
both method run(Consumer<Integer>) in Test and
method run(Function<Integer,Integer>) in Test match
To me, intuitively, this doesn't make sense. There is absolutely no ambiguity between a lambda expression that yields a return value ("value-compatible") and a lambda expression that yields void
("void-compatible"), as set out in the JLS §15.27.
But of course, the JLS is deep and complex and we inherit 20 years of backwards compatibility history, and there are new things like:
Certain argument expressions that contain implicitly typed lambda expressions (§15.27.1) or inexact method references (§15.13.1) are ignored by the applicability tests, because their meaning cannot be determined until a target type is selected.
The above limitation is probably related to the fact that JEP 101 wasn't implemented all the way, as can be seen here and here.
Question:
Who can tell me exactly what parts of the JLS specifies this compile-time ambiguity (or is it a compiler bug)?
Bonus: Why were things decided this way?
Update:
With jdk1.8.0_40, the above compiles and works fine