@FunctionalInterface
interface MyIF {
void init();
default void myTest() {
System.out.println("myTest interface Method");
}
}
class A implements MyIF {
@Override
public void init() {
myTest();
}
@Override
public void myTest() {
System.out.println("myTest class Method");
}
}
public class Main {
public static void main(String[] args) {
A a = new A();
MyIF my = a::myTest;
my.myTest();
}
}
- 产出**
myTest接口方法
- 预期**
myTest类方法
我尝试了这段代码,并期待相同的结果:
A a = new A();
MyIF my = new A();
my.myTest();
- 产出**
myTest类方法
为什么结果不同?
2条答案
按热度按时间xsuvu9jc1#
a::myTest
表示使用myTest()
作为函数接口MyIF
的实现中所需的函数。它必须替换的函数是init()
方法,而不是myTest
方法。函数接口缺少一个实现,在这种情况下,它是init()
方法。因此MyIF
的这个新实现具有由a::myTest
指定的init
,以及由default void myTest()
在MyIF
中指定的myTest
。它不是A
的示例:这就像拥有:在第二种情况下,您的
my
* 实际上是A
的一个示例,并且类中的方法实现覆盖了接口中的默认实现,因此您从A
获得了myTest
方法。pinkon5k2#
这是一个很好的问题:)。
正如@khelwood所指出的,这句台词:
创建到MyIF接口的
init()
方法的lambda绑定。当编译器遇到这种情况时,它会创建一个新的MyIF引用,该引用只链接到A的示例,用于实现
init()
。由于编译器只能选择一个方法来提供@FunctionalInterface
行为,它必须选择非默认的方法,否则编译器无法知道接口将哪个方法定义为它的函数/lambda签名。如果您尝试使用两个没有默认实现的标准接口方法,您将因此而得到一个编译器错误(即使签名不同)。如果在代码中添加一行代码,可能会更清楚:
现在,您可以在输出中看到,lambda调用的
init()
方法仍然调用A中的myTest()
实现。一般来说,避免函数接口中的默认实现以减少混淆可能是明智的:)。
Effective Java(第3版)第21项和第43项与此相关。