I\'ve come across a weird problem where a method reference to Thread::sleep
is ambiguous but a method with the same signature is not.
package test;
You can recreate the problem in your own class by adding a method sleep
with two arguments to class Test like below:
public static void sleep(long millis) {
}
public static void sleep(long millis, int nanos) {
}
So the problem is really caused by the fact that the method sleep is overloaded.
The JLS indicates that the initial method selection code only looks at the number of type arguments to the functional interface - only in the second phase does it look at the signature of the method inside the functional interface.
It is not possible to specify a particular signature to be matched, for example, Arrays::sort(int[]). Instead, the functional interface provides argument types that are used as input to the overload resolution algorithm (§15.12.2).
(the second-to-last paragraph of this section)
So in the case of Thread::sleep
, void sleep(long)
potentially matches functional interface FooVoid
, while overload void sleep(long, int)
potentially matches functional interface Foo
. That's why you get the "reference to foo is ambiguous" error.
When it tries to go further and see how to match Foo
with functional method R call(P param1)
to the method void sleep(long, int)
, it finds out that this is not actually possible, and you get another compile error:
test/Test.java:7: error: incompatible types: cannot infer type-variable(s) P,R
foo(Thread::sleep, 1000L); // error
^
(argument mismatch; bad return type in method reference
void cannot be converted to R)