Please consider this example:
import java.util.function.Consumer;
public class Example {
public static void main(String[] args) {
Example example = new Example();
example.setConsumer(test -> System.out.println("passed string is " + test)); //uses MyConsumer, why ?
example.getConsumer().accept("Test 1");
example.setConsumer((MyConsumer<String>)test -> System.out.println("passed string is " + test)); //uses MyConsumer
example.getConsumer().accept("Test 2");
example.setConsumer((Consumer<String>)test -> System.out.println("passed string is " + test)); //uses Consumer
example.getConsumer().accept("Test 3");
}
private Consumer<String> consumer;
public Consumer<String> getConsumer() {
return consumer;
}
public void setConsumer(Consumer<String> consumer) {
this.consumer = consumer;
}
public void setConsumer(MyConsumer<String> consumer) {
this.consumer = consumer;
}
@FunctionalInterface
public interface MyConsumer<T> extends Consumer<T> {
@Override
default void accept(T value) {
System.out.println("In consumer string: " + value); //example thing to do
receive(value);
}
void receive(T value);
}
}
What interests me here is the first test. Why is it using MyConsumer instead of Consumer ? What if I had more different possible Consumers with the same lambda structure, who has priority ? Plus, the cast I do on Test 2 is marked as Redundant
by my IDE. That means the lamdba is created as a MyConsumer first. Why so ?
I'm using IntelliJ Idea with Javac.
Runnable is a functional interface, that's why we can use lambda expression to create it's instance. Since run() method takes no argument, our lambda expression also have no argument.
Lambda expression provides implementation of functional interface. An interface which has only one abstract method is called functional interface. Java provides an anotation @FunctionalInterface, which is used to declare an interface as functional interface.
function Description. Functional interfaces provide target types for lambda expressions and method references. Each functional interface has a single abstract method, called the functional method for that functional interface, to which the lambda expression's parameter and return types are matched or adapted.
A functional interface must have exactly one abstract method. A functional interface has any number of default methods because they are not abstract and implementation already provided by the same. A functional interface declares an abstract method overriding one of the public methods from java. lang.
It's according to the procedure of choosing the most specific method as defined by the language specification:
If more than one member method is both accessible and applicable to a method invocation, it is necessary to choose one to provide the descriptor for the run-time method dispatch. The Java programming language uses the rule that the most specific method is chosen.
...
A functional interface type S is more specific than a functional interface type T for an expression e if T is not a subtype of S and one of the following is true (where U1 ... Uk and R1 are the parameter types and return type of the function type of the capture of S, and V1 ... Vk and R2 are the parameter types and return type of the function type of T):
- If e is an explicitly typed lambda expression (§15.27.1), then one of the following is true:
R2 is void.
R1 <: R2.
R1 and R2 are functional interface types, and there is at least one result expression, and R1 is more specific than R2 for each result expression of e.
(The result expression of a lambda expression with a block body is defined in §15.27.2; the result expression of a lambda expression with an expression body is simply the body itself.)
R1 is a primitive type, and R2 is a reference type, and there is at least one result expression, and each result expression of e is a standalone expression (§15.2) of a primitive type.
R1 is a reference type, and R2 is a primitive type, and there is at least one result expression, and each result expression of e is either a standalone expression of a reference type or a poly expression.
- If e is an exact method reference expression (§15.13.1), then i) for all i (1 ≤ i ≤ k), Ui is the same as Vi, and ii) one of the following is true:
R2 is void.
R1 <: R2.
R1 is a primitive type, R2 is a reference type, and the compile-time declaration for the method reference has a return type which is a primitive type.
R1 is a reference type, R2 is a primitive type, and the compile-time declaration for the method reference has a return type which is a reference type.
If e is a parenthesized expression, then one of these conditions applies recursively to the contained expression.
If e is a conditional expression, then for each of the second and third operands, one of these conditions applies recursively.
Therefore, MyConsumer
is more specific than Consumer
because Consumer
(T
in the spec) is not a subtype and both have a return value of void
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With