簡體   English   中英

Java 8 Lambda語法更改

[英]Java 8 Lambda Syntax change

我遇到了一個問題,其中Lambda的允許語法在java編譯器的1.8.0_05和1.8.0_20(beta)版本之間發生了變化。

例:

package scratch;

import javafx.scene.control.MenuItem;

public class Test
{
    public void test()
    {
        MenuItem mi = new MenuItem();

        //This compiles anywhere
        mi.setOnAction(e -> System.out.println("hi"));

        //as does this
        mi.setOnAction(e -> {System.out.println("hi");});

        //This doesn't on build 1.8.0_20-ea-b13 - but does on build 1.8.0_05-b13
        mi.setOnAction(e -> (System.out.println("hi")));
    }
}

我想知道的 - 最后一個例子是有效的Lambda表達式嗎? 他們剛剛收緊了編譯器驗證? 或者最新的1.8編譯器中是否有錯誤?

最新編譯器打印的錯誤是:

/scratch/src/scratch/Test.java:18: error: method setOnAction in class MenuItem cannot be applied to given types;
                mi.setOnAction(e -> (System.out.println("hi")));
                  ^
  required: EventHandler<ActionEvent>
  found: (e)->(Syst[...]hi"))
 reason: argument mismatch; bad return type in lambda expression
      missing return value
1 error

編輯(因為我似乎無法在回復中格式化評論):

setOnAction方法的實現是:

public final void setOnAction(EventHandler<ActionEvent> value) {
    onActionProperty().set( value);
}

和EventHandler:

@FunctionalInterface
public interface EventHandler<T extends Event> extends EventListener {
    /**
     * Invoked when a specific event of the type for which this handler is
     * registered happens.
     *
     * @param event the event which occurred
     */
    void handle(T event);
}

在Java編程語言中,方法調用表達式是一個表達式語句 ,一種可以出現在需要表達式或需要語句的地方的構造。

因此,即使方法返回void也可以使用簡化表達式形式param -> expression作為用例e -> System.out.println("hi") 由於此處預期的函數簽名是<T extends Event> T -> void ,因此包含單個void方法調用的lambda表達式對此上下文有效。

當您嘗試在需要表達式的其他上下文中使用表達式語句時,情況會發生變化。 比較JLS§15.1

當且僅當它是調用不返回值的方法的方法調用(第15.12節)時,表達式才表示什么,即聲明為void的方法(第8.4節)。 這樣的表達式只能用作表達式語句(§14.8),因為表達式可以出現的每個其他上下文都需要表達式來表示某些東西。

正式應用這個規則,即使簡單地在(System.out.println("hi"))放置括號也是無效的,因為這是一個復合表達式,試圖在上下文中使用方法調用聲明為void的方法真實的表達“(返回一個值)是必需的。

所以使用無效表達式的lambda表達式如mi.setOnAction(e -> (System.out.println("hi"))); 也無效。 該消息有點誤導。 似乎編譯器關注的是表單( whatever )表達式是非語句表達式,因此在void上下文中void 但是,報告在圓括號中放置void方法調用的初始錯誤會更有用。

你不能把( … )圍繞一個void方法調用的規則沒有改變,所以錯誤是較舊的編譯器接受這種語法,現在似乎已經修復了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM