JavaFX 事件处理之谜 - 删除了代码,事件仍在处理?



我在Java和C#等OOP语言方面很有经验。直到现在才惹过FX,并且出于办公室的无聊而开始玩弄处理事件。

我的 FX 应用程序都是在一个类中编写的。我导入了我想要的包,包括这两个:

import javafx.event.ActionEvent;
import javafx.event.EventHandler;

我在 Main 类声明上实现了具有 ActionEvent 类型的 EventHandler 接口,如下所示。

public class Main extends Application implements EventHandler<ActionEvent>

我在按钮对象上编写了一个匿名内部类来处理这样的单击事件。

btnButton.setOnAction(new EventHandler<ActionEvent>(){
public void handle(ActionEvent event) {
System.out.println("I got clicked");
}
});

它显然像它应该的那样工作,但后来我做了一个实验。我从上面删除了两个导入。我删除了 Main 类声明的"实现"部分。这使我的应用程序没有任何对事件处理的引用。然后我回到我的按钮对象并将事件处理程序编写为 lambda 表达式,如下所示......

btnButton.setOnAction(e -> System.out.println("I got touched"));

你猜怎么着?它仍然有效!!这是不可能的..有人可以解释一下在删除处理事件所需的代码后它仍然如何工作吗?这有点好笑,让我大吃一惊。

提前感谢您的回复!

-开普勒IO

您没有删除事件处理所需的代码:

public class Main extends Application implements EventHandler<ActionEvent>

从来不需要使用Main类实现EventHandler<ActionEvent>,因为无论如何您都使用 anonymus 类作为事件处理程序,而不是

btnButton.setOnAction(this);

(假设this在此处引用Main实例)

lambda 的另一个好处是,只要 java 编译器仍然能够明确地确定您正在实现的接口(从而确定方法的签名),您就可以省略参数类型。

在这种情况下,setOnAction方法不会重载,Java 编译器可以确定参数的类型为EventHandler<ActionEvent>,并且要实现的方法的签名为

public void handle(ActionEvent event)

因此

btnButton.setOnAction((ActionEvent e) -> System.out.println("I got touched"));

甚至

btnButton.setOnAction(e -> System.out.println("I got touched"));

"满足"编译器。


如果setOnAction方法重载,这将有所不同Button

public void setOnAction(Consumer<Integer> x) { ... }

在这种情况下,编译器将需要其他信息来确定要使用的方法:

btnButton.setOnAction((Integer a) -> System.out.println("something"));
btnButton.setOnAction((ActionEvent a) -> System.out.println("something"));
btnButton.setOnAction((Consumer<Integer>) a -> System.out.println("something"));
btnButton.setOnAction((EventHandler<ActionEvent>) a -> System.out.println("something")); 

如果您有兴趣在规范中查找此内容,以下是相关部分:

  • JLS: 15.表达式
                 12.方法调用表达式
                        编译时步骤 2:确定方法签名
                              5.选择最具体的方法
  • JLS: 15.表达式
                  27.拉姆达表达式

相关内容

  • 没有找到相关文章

最新更新