首页 > 解决方案 > 如何在不使用 Lambda 的情况下编写此代码并且仍然可以正常工作?

问题描述

我正在尝试在不使用 lambda 的情况下将此代码转换为工作,以便我可以更好地理解它,但我一点运气都没有。如何用ActionEvent类似于按钮的 s 来编写它?

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

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

标签: javalambdaactionevent

解决方案


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

lambda 是实现功能接口的一种简写方式,它是一个interface带有单个(非default)方法的方法。没有 lambda 的等效代码是:

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

就是这样。它只是用于实例化匿名并实现其单一方法的语法糖† 。EventHandlerhandle()

我省略了方法主体,因为两者都相同。

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

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

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

 

正如@user 指出的那样,它实际上更复杂。Lambdas 并不总是对匿名类脱糖。通常编译器可以做一些更有效的事情。但从概念上讲,将它们视为匿名类是一种在心理上翻译它们的好方法。


推荐阅读