I see Thread()
takes both Runnable
and String
for single argument constructors. How does the compiler know that a lambda
is implementing a Runnable
class and not a String
class?
(new Thread( () -> {
System.out.println("Deleting stats...");
})).start();
Maybe it goes by the number of methods in the class/interface? But what if a class had multiple constructors that took single argument class that only had one method, for example:
Thread( Runnable r );
Thread( Comparable c );
Thread( ActionListener al );
What happens then when you try to implement a lambda
then? How would the compiler know which class the lambda
is implementing?
The Java compiler must choose a functional interface type for the type of a lambda expression. This is governed by the JLS, Section 15.27.3, which states:
A lambda expression is compatible in an assignment context, invocation context, or casting context with a target type T if T is a functional interface type (§9.8) and the expression is congruent with the function type of the ground target type derived from T.
The type String
is not a functional interface type, but Runnable
is. The lambda takes no arguments and returns no data, so it is congruent with Runnable
.
More generally, the types of parameters in a lambda expression must match the types of parameters of the single abstract method of a functional interface type, and the return types must match also.
In your example, each of the 3 functional interface types is distinct, so at most one will match. If there are multiple functional interface types that could possible match, that would be ambiguous, only resolvable by casting the lambda expression to the intended functional interface type.