有没有办法捕获某种类型的所有功能接口?

时间:2014-05-02 10:51:23

标签: 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) { }
}

它是签名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 ,然后我们可以看到两个客户需要实现自己的具体功能界面。 因此需要一种方法来概括其用法。

3 个答案:

答案 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);
}

如果我们按照您最初认为应该可行的方式,那么我们会很快遇到问题:viewCardConsumerConsumer<Card>}没有onCardPlayed方法!

在你的情况下,例子也是如此,

private void acceptConsumer(final Consumer<Card> cardConsumer) {
    cardConsumer.apply(new Card());
}

如果您将OnHandCardAddedListener传递给此方法,则它不包含apply方法。

鉴于这些例子,我不希望它 - 我也不希望它 - 工作&#34;开箱即用&#34;。