【问题标题】:Lambda expression issue in NetbeansNetbeans 中的 Lambda 表达式问题
【发布时间】:2014-05-02 13:56:12
【问题描述】:

我在 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 -&gt; counter.incrementAndGet() 实现了SAM HandView.OnCardAddedListener,它是HandView 的子类型,所以应该是正确的,对吧?

【问题讨论】:

  • 还在玩纸牌游戏,嗯? :) 仅供参考,对于我来说,没有强制转换的版本也不能在 Eclipse 中编译(类型推断可能不够聪明)。但是,带有 cast 的版本不会显示任何冗余警告。
  • 我对你关于哪个版本的代码可以工作或不能与哪个编译器一起工作的说法有点困惑。尝试使用 Eclipse、Netbeans 8.0 和 jdk1.8.0_05 的 javac,我遇到了与所有这些相同的行为,需要强制转换并且没有收到关于强制转换冗余的警告。这就是我所期望的。

标签: java netbeans lambda java-8 netbeans-8


【解决方案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();

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

【讨论】:

    【解决方案2】:

    你应该尽可能使用@FunctionalInterface

    如果你注释你的HandView 接口

    @FunctionalInterface
    public interface HandView extends View<Hand> {
    

    你会得到一个编译错误,HandView 接口不起作用,即。它声明了多个abstract 方法。


    当你施放它时

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

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

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

    【讨论】:

      猜你喜欢
      • 2011-05-09
      • 2011-01-02
      • 2020-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-16
      相关资源
      最近更新 更多