我在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.拉姆达表达式