2

我在 Netbeans 8.0 中的 Lambda 表达式有问题,想知道我是否做错了什么,或者 Netbeans 或 javac 编译器做错了什么。

我有以下代码:

public interface HandView extends View<Hand> {
    void onCardAdded(final Card card);

    void onCardPlayed(final int cardIndex);

    void onCardsSwapped(final int cardIndexOne, final int cardIndexTwo);

    public static HandView merge(final HandView... handViews) {
        return new HandView() {
            @Override
            public void onCardAdded(final Card card) {
                Arrays.stream(handViews).forEach(handView -> handView.onCardAdded(card));
            }

            @Override
            public void onCardPlayed(final int cardIndex) {
                Arrays.stream(handViews).forEach(handView -> handView.onCardPlayed(cardIndex));
            }

            @Override
            public void onCardsSwapped(final int cardIndexOne, final int cardIndexTwo) {
                Arrays.stream(handViews).forEach(handView -> handView.onCardsSwapped(cardIndexOne, cardIndexTwo));
            }
        };
    }

    @FunctionalInterface
    public static interface OnCardAddedListener extends HandView, Consumer<Card> {
        @Override
        default void accept(final Card card) {
            onCardAdded(card);
        }

        @Override
        void onCardAdded(final Card card);

        @Override
        default void onCardPlayed(final int cardIndex) { }

        @Override
        default void onCardsSwapped(final int cardIndexOne, final int cardIndexTwo) { }
    }

    @FunctionalInterface
    public static interface OnCardPlayedListener extends HandView, IntConsumer {
        @Override
        default void accept(final int cardIndex) {
            onCardPlayed(cardIndex);
        }

        @Override
        default void onCardAdded(final Card card) { }

        @Override
        void onCardPlayed(final int cardIndex);

        @Override
        default void onCardsSwapped(final int cardIndexOne, final int cardIndexTwo) { }
    }

    @FunctionalInterface
    public static interface OnCardsSwappedListener extends HandView {
        @Override
        default void onCardAdded(final Card card) { }

        @Override
        default void onCardPlayed(final int cardIndex) { }

        @Override
        void onCardsSwapped(final int cardIndexOne, final int cardIndexTwo);
    }
}

然后我将其用于:

AtomicInteger counter = new AtomicInteger(0);
HandView handView = card -> counter.incrementAndGet();

Netbeans 给出以下消息:

incompatible types: HandView is not a functional interface
    multiple non-abstract methods found in interface HandView

然后我将决定手动转换它:

HandView handView = 
    (HandView.OnCardAddedListener)card -> counter.incrementAndGet();

现在它警告我演员阵容是多余的。

当我在 Netbeans 8.0 中使用原始版本编译它时,它编译得很好,没有任何编译(或运行时)错误。现在谁有错?

我会说它card -> counter.incrementAndGet()实现了SAM HandView.OnCardAddedListener,它是 的子类型HandView,所以它应该是正确的,对吧?

4

2 回答 2

1

我认为您从 Netbeans 收到的错误消息是正确的:

public interface HandView extends View<Hand> {
    void onCardAdded(final Card card);

    void onCardPlayed(final int cardIndex);

    void onCardsSwapped(final int cardIndexOne, final int cardIndexTwo);

    (...)
}

这确实不是功能接口。

关于这条线:

HandView handView = 
    (HandView.OnCardAddedListener)card -> counter.incrementAndGet();

我会这样写:

HandView.OnCardAddedListener handView = card -> counter.incrementAndGet();

我希望编译器能够更好地处理,没有任何警告。

于 2014-05-02T14:20:11.907 回答
1

你应该@FunctionalInterface尽可能地利用。

如果你注释你的HandView界面

@FunctionalInterface
public interface HandView extends View<Hand> {

您将收到HandView接口不起作用的编译错误,即。它声明了不止一种abstract方法。


当你施放它时

HandView handView = 
(HandView.OnCardAddedListener)card -> counter.incrementAndGet();

它应该工作。该上下文中的 lambda 表达式,即。在HandView.OnCardAddedListener预期 a 的地方,将看到OnCardAddedListener哪个是 a @FunctionalInterface。因此,可以从 lambda 表达式创建一个实例。

完整性的附加信息:考虑到函数式接口可以有任意数量的默认或静态方法,例如参见 java.util.function.Function。

于 2014-05-02T14:29:02.253 回答