如何在不使用 Lambda 的情况下编写此代码并使其仍然有效?

How do I write this code without using Lambda and still have it work?

我试图将此代码转换为在不使用 lambda 的情况下工作,以便我可以更好地理解它,但我一点运气都没有。怎么写成类似按钮的ActionEvent

enemyBoard = new Board(true, event -> {
    if (!running)
        return;

    Cell cell = (Cell) event.getSource();
    if (cell.wasShot)
        return;

    enemyTurn = !cell.shoot();

    if (enemyBoard.ships == 0) {
        System.out.println("YOU WIN");
        System.exit(0);
    }

    if (enemyTurn)
        enemyMove();
});

这是 Board 构造函数:

public Board(boolean enemy, EventHandler<? super MouseEvent> handler) {
    this.enemy = enemy;
    for (int y = 0; y < 10; y++) {
        HBox row = new HBox();
        for (int x = 0; x < 10; x++) {
            Cell c = new Cell(x, y, this);
            c.setOnMouseClicked(handler);
            row.getChildren().add(c);
        }

        rows.getChildren().add(row);
    }

    getChildren().add(rows);
}

该代码属于战舰游戏,这里是link游戏代码:https://github.com/AlmasB/Battleship/tree/master/src/com/almasb/battleship.

enemyBoard = new Board(true, event -> {
    ...
});

lambda 是 shorthand 实现 functional interface 的方法,它是一个 interface 和一个(非 default)方法。没有 lambda 的等效代码是:

enemyBoard = new Board(true, new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        ...
    }
});

就是这样。它只是语法糖 用于实例化匿名 EventHandler 并实现其单个 handle() 方法。

我省略了方法体,因为两者是一样的。

如果这看起来仍然很奇怪,写 new ClassOrInterface() { ... } 本身也是一种语法糖。我们可以应用另一轮脱糖并显式写出匿名 class:

class EventHandler implements EventHandler<MouseEvent> {
    public void handle(MouseEvent event) {
        ...
    }
}
enemyBoard = new Board(true, new EventHandler());

请注意 EventHandler 是一个自动生成的 class 名称,保证不会与任何其他真实的 class 冲突。编译器使用 $ 字符来命名 class,这在最终用户代码中是不合法的,这样就不会发生冲突。如果您曾经在堆栈跟踪中看到 class 带有美元符号的名称,这就是它们的来源:匿名 classes.

一样,背后其实更复杂。 Lambda 并不总是对匿名 class 脱糖。通常编译器可以做一些更有效率的事情。但从概念上讲,将它们视为匿名的 classes 是在心理上翻译它们的好方法。