I have an overloaded method that uses two different functional interfaces as parameters ( Runnble and Supplier ). System.out.println explicitly compatible only with Runnable , because it is a void method. However, the compiler still claims that the call is ambiguous. How is this possible?
import java.util.function.Supplier; public class GenericLambdas { public static void main(String[] args) { wrap(System.out::println); // Compiler error here wrap(() -> {}); // No error wrap(System.out::flush); // No error } static <R> void wrap(Supplier<R> function) {} static void wrap(Runnable function) {} }
Compiler Output:
Error:Error:line (5)java: reference to wrap is ambiguous both method <R>wrap(java.util.function.Supplier<R>) in GenericLambdas and method wrap(java.lang.Runnable) in GenericLambdas match Error:Error:line (5)java: incompatible types: cannot infer type-variable(s) R (argument mismatch; bad return type in method reference void cannot be converted to R)
Based on the second error ( argument mismatch, void cannot be converted to R ), should the compiler not eliminate the ambiguity of the call? Then this will take care of all the compiler errors (since it will not be ambiguous and will not try to convert void to R).
And why can you enable () -> {} and System.out::flush ? They have the same signature as System.out.println . Suppose System.out.println overloaded with versions that take an argument, but none of these overloaded versions matches either Supplier or Runnable , so I donβt see how important they are here.
EDIT:
This seems to compile and run using the Eclipse compiler . Which compiler is right, or is behavior allowed?
java lambda java-8 type-inference functional-interface
Yosef weiner
source share