I was answering a question and ran into a scenario I can\'t explain. Consider this code:
interface ConsumerOne {
void accept(T a);
}
interface Cust
The Eclipse compiler correctly resolves to the default
method, since this is the most specific method according to the Java Language Specification 15.12.2.5:
If exactly one of the maximally specific methods is concrete (that is, non-
abstract
or default), it is the most specific method.
javac
(used by Maven and IntelliJ by default) tells the method call is ambiguous here. But according to Java Language Specification it is not ambiguous since one of the two methods is the most specific method here.
Implicitly typed lambda expressions are handled differently than explicitly typed lambda expressions in Java. Implicitly typed in contrast to explicitly typed lambda expressions fall through the first phase to identify the methods of strict invocation (see Java Language Specification jls-15.12.2.2, first point). Hence, the method call here is ambiguous for implicitly typed lambda expressions.
In your case, the workaround for this javac
bug is to specify the type of the functional interface instead of using an explicitly typed lambda expression as follows:
iterable.forEach((ConsumerOne) aList::add);
or
iterable.forEach((Consumer) aList::add);
Here is your example further minimized for testing:
class A {
interface FunctionA { void f(A a); }
interface FunctionB { void f(A a); }
interface FooA {
default void foo(FunctionA functionA) {}
}
interface FooAB extends FooA {
void foo(FunctionB functionB);
}
public static void main(String[] args) {
FooAB foo = new FooAB() {
@Override public void foo(FunctionA functionA) {
System.out.println("FooA::foo");
}
@Override public void foo(FunctionB functionB) {
System.out.println("FooAB::foo");
}
};
java.util.List list = new java.util.ArrayList();
foo.foo(a -> list.add(a)); // ambiguous
foo.foo(list::add); // ambiguous
foo.foo((A a) -> list.add(a)); // not ambiguous (since FooA::foo is default; javac bug)
}
}