Win*_*ter 5 java lambda java-8 functional-interface
请考虑这个例子:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
我最感兴趣的是第一次测试.为什么使用MyConsumer而不是Consumer?如果我有更多不同的消费者具有相同的lambda结构,谁具有优先权呢?另外,我在测试2上进行的演员表Redundant由我的IDE 标记.这意味着lamdba首先被创建为MyConsumer.为什么这样 ?
我正在使用IntelliJ Idea和Javac.
如果多个成员方法都可访问并适用于方法调用,则必须选择一个为运行时方法调度提供描述符.Java编程语言使用选择最具体方法的规则.
...
如果T不是S的子类型且下列之一为真,则功能接口类型S 比表达式e的功能接口类型T 更具体(其中U1 ... Uk和R1是参数类型和返回类型捕获S的函数类型,V1 ... Vk和R2是T)函数类型的参数类型和返回类型:
- 如果e是显式类型的lambda表达式(第15.27.1节),则以下之一为真:
R2无效.
R1 <:R2.
R1和R2是功能接口类型,并且对于e的每个结果表达式,存在至少一个结果表达式,并且R1比R2更具体.
(具有块体的lambda表达式的结果表达式在§15.27.2中定义;具有表达式主体的lambda表达式的结果表达式就是主体本身.)
R1是基本类型,R2是引用类型,并且至少有一个结果表达式,e的每个结果表达式是基本类型的独立表达式(第15.2节).
R1是引用类型,R2是基本类型,并且至少有一个结果表达式,e的每个结果表达式都是引用类型的独立表达式或多义表达式.
- 如果e是精确的方法参考表达式(§15.13.1),则i)对于所有i(1≤i≤k),Ui与Vi相同,并且ii)以下之一为真:
R2无效.
R1 <:R2.
R1是基本类型,R2是引用类型,方法引用的编译时声明具有返回类型,它是基本类型.
R1是引用类型,R2是基本类型,方法引用的编译时声明具有返回类型,它是引用类型.
如果e是带括号的表达式,则这些条件之一递归地应用于包含的表达式.
如果e是条件表达式,则对于第二和第三操作数中的每一个,递归地应用这些条件之一.
因此,MyConsumer更具体的是Consumer因为Consumer(T在规范中)不是子类型并且都具有返回值void.