这些在 JavaFX 中使用事件的方法是否相同?

Are these methods of using event identical in JavaFX?

我有一个按钮,我希望在将鼠标悬停在该按钮上时显示文本。

这两种方法都有效,但它们可以互换使用吗?

// First
EventHandler<MouseEvent> eventHandler = new EventHandler<MouseEvent>() {
    @Override
    public void handle(MouseEvent e) {
        System.out.println("Hello World");
    }
};
button.setOnMouseEntered(eventHandler);

// Second. Lambda expression.
button.setOnMouseEntered(e -> {
    System.out.println("Hello ");
});

第一个不太明白。我假设 EventHandler<MouseEvent> 是类型,eventHandler 是对象的名称。正确的?

是的,它们将执行相同的代码。

第一个是所谓的匿名class。这意味着您可以直接覆盖继承接口的方法(在本例中为 handle),而不必使用额外的 classes/interfaces.

然后将处理程序实例传递给 setOnMouseEntered 方法。

lambda 表达式也这样做,但由于该方法需要特定的对象类型,您可以使用 lambda 表达式将其写得更短。

eeventHandler

基本相同

第一个是匿名内部class,其中覆盖了handle方法。这是在 lambda 表达式之前执行侦听器和处理程序的方法。现在,如果 class 是一个函数式接口(只有 1 个抽象方法,比如 EventHandler 在你的情况下只有它的方法 handle),那么可以使用 lambda 表达式代替 anonim class.

这两个方法确实是一样的,但是首选使用lambdas,因为代码会更紧凑,更容易理解。

我相信第一个例子可以明确地写成:

private class MouseHandler implements EventHandler<MouseEvent> {
    public void handle(MouseEvent e) {
        System.out.println("Hello World");
    }
}
button.setOnMouseEntered(new MouseHandler());

这可以通过匿名 class 和 lambda 表达式来减少。我的理解是,这是唯一可能的,因为 EventHandler 是一个功能接口。

已经提供的两个答案都很好,但我想添加另一个考虑因素。

只要有可能,最好使用 lambda,不仅因为它们更易于阅读,而且在编译时也会产生截然不同的字节码。

在第一个示例中,编译器创建了一个单独的 class(例如:OuterClass)。这个 class 必须在每次调用时实例化,这将在某个时候被垃圾收集。

在第二个示例中,lambda 被编译为包含 class 的本地方法。这意味着它只是一个简单的方法调用。

根据它的调用频率,这可能是一个重要的考虑因素。