假设我有以下手工制作的功能界面:
@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) { }
}
它是签名Card -> void
,因此该功能接口的实现是lambda,它是Consumer<Card>
功能接口的实现。
我知道我应该扩展Consumer<Card>
并使用apply
界面中的默认方法实现OnHandCardAddedListener
。
但为什么不只是开箱即用?
使用以下方法进行测试:
private void acceptConsumer(final Consumer<Card> cardConsumer) {
}
和testcode:
Consumer<Card> cardConsumer = card -> { };
acceptConsumer(cardConsumer);
OnHandCardAddedListener viewCardConsumer = card -> { };
acceptConsumer(viewCardConsumer); // does not compile
这里acceptConsumer(viewCardConsumer)
无法编译,但为什么不编译?据我所知,他们应该解决相同类型的lambda,因此两者都可以用于具体的定义。
编辑,我忘了提到为什么这很重要,请考虑我需要使用 java提供不的功能界面的情况.util.function ,然后我们可以看到两个客户需要实现自己的具体功能界面。 因此需要一种方法来概括其用法。
答案 0 :(得分:5)
这不起作用的原因是您已经为lambda表达式指定了一个类型。
考虑这个例子:
acceptConsumer(card -> {});
这里,编译器可以检查参数的类型应该是什么。由于提供的lambda是该参数类型的合法表示,所以一切都很好 将此与您的示例进行比较:
OnHandCardAddedListener viewCardConsumer = card -> { };
acceptConsumer(viewCardConsumer); // does not compile
这里你没有将lambda传递给方法,而是一种与预期完全不同的类型。使用lambda表达式初始化viewCardConsumer
这一事实完全无关紧要。此代码等同于以下代码,我认为您不希望编译:
OnHandCardAddedListener viewCardConsumer = new OnHandCardAddedListener() {
@Override
void onCardAdded(final Card card){ };
};
acceptConsumer(viewCardConsumer); // does not compile either
答案 1 :(得分:2)
尝试(未经测试):
acceptConsumer(viewCardConsumer::onCardAdded);
修改强>
为什么这样做而另一个没有?
一个是普通的旧Java方法调用,OnHandCardAddedListener不扩展Consumer。提供的解决方案是一个方法引用,它有自己的规则:只有输入和输出参数(和例外?)必须匹配。
答案 2 :(得分:0)
考虑一下这种可能性:
Consumer<Card> viewCardConsumer = card -> { };
acceptConsumer(viewCardConsumer);
private void acceptConsumer(final OnHandCardAddedListener<Card> cardConsumer) {
cardConsumer.onCardPlayed(1);
}
如果我们按照您最初认为应该可行的方式,那么我们会很快遇到问题:viewCardConsumer
(Consumer<Card>
}没有onCardPlayed
方法!
在你的情况下,例子也是如此,
private void acceptConsumer(final Consumer<Card> cardConsumer) {
cardConsumer.apply(new Card());
}
如果您将OnHandCardAddedListener
传递给此方法,则它不包含apply
方法。
鉴于这些例子,我不希望它 - 我也不希望它 - 工作&#34;开箱即用&#34;。