ski*_*iwi 1 java lambda java-8
假设我有以下手工制作的功能界面:
@FunctionalInterface
public static interface OnHandCardAddedListener extends HandView {
@Override
void onCardAdded(final Card card);
@Override
default void onCardPlayed(final int cardIndex) { }
@Override
default void onCardsSwapped(final int cardIndexOne, final int cardIndexTwo) { }
}
Run Code Online (Sandbox Code Playgroud)
它是签名Card -> void
,因此该功能接口的实现是lambda,它是Consumer<Card>
功能接口的实现.
我知道我可能应该在界面中使用默认方法扩展Consumer<Card>
和实现它.apply
OnHandCardAddedListener
但为什么不只是开箱即用?
使用以下测试:
private void acceptConsumer(final Consumer<Card> cardConsumer) {
}
Run Code Online (Sandbox Code Playgroud)
和测试代码:
Consumer<Card> cardConsumer = card -> { };
acceptConsumer(cardConsumer);
OnHandCardAddedListener viewCardConsumer = card -> { };
acceptConsumer(viewCardConsumer); // does not compile
Run Code Online (Sandbox Code Playgroud)
这里acceptConsumer(viewCardConsumer)
不编译,但为什么不编译?据我所知,他们应该解决相同类型的lambda,因此两者都可以用于具体的定义.
编辑,我忘了提到为什么这很重要,考虑我需要使用java.util.function 没有提供的功能接口的情况,然后我们可以看到两个客户需要实现自己的具体功能做同样的接口.
因此需要一种方法来概括其用法.
这不起作用的原因是您已经为lambda表达式分配了一个类型.
考虑这个例子:
acceptConsumer(card -> {});
Run Code Online (Sandbox Code Playgroud)
在这里,编译器可以检查参数的类型应该是什么.由于提供的lambda是该参数类型的合法表示,所以一切都很好.
将此与您的示例进行比较:
OnHandCardAddedListener viewCardConsumer = card -> { };
acceptConsumer(viewCardConsumer); // does not compile
Run Code Online (Sandbox Code Playgroud)
在这里,您没有将lambda传递给方法,而是一种与预期完全不同的类型.使用lambda表达式进行初始化的事实viewCardConsumer
完全无关紧要.此代码等同于以下代码,我认为您不希望编译:
OnHandCardAddedListener viewCardConsumer = new OnHandCardAddedListener() {
@Override
void onCardAdded(final Card card){ };
};
acceptConsumer(viewCardConsumer); // does not compile either
Run Code Online (Sandbox Code Playgroud)