如何在 ActionListener 中创建类似 lambda 的模式

Posted

技术标签:

【中文标题】如何在 ActionListener 中创建类似 lambda 的模式【英文标题】:How to create a lambda-like pattern in ActionListener 【发布时间】:2017-12-01 03:13:54 【问题描述】:

我如何从 lambda 编写类似这样的函数:

jButton.addActionListener(ae -> callAnyMethod());

因为我正在创建一个库并且想自己实现这样的模式。 在 Java 8 和 lambda 发布之前,有人会如何制作这样的模式?就像我试图接近的是:

我正在尝试在我的 CustomButton ActionListener 的 actionPerformed 方法中设置一个占位符并调用如下方法:

CustomButton.CustomButtonListener(placeholder method (); ) 

而用户只需要创建一个方法并将其写入砖块中......例如名为 def() 的方法:

CustomButton.CustomButtonListener(def());

def 将自动传递给我的 CustomButtonListener 的 actionPerformed 方法,并在按钮单击时触发

编辑:

这就是我目前想出的代码:

作为方法存储在我的 CustomButton 类中的 ActionListener:

public void CustomButtonListener(Object object)

        addActionListener(new ActionListener()

@Override
        public void actionPerformed(ActionEvent e) 



          // how to call the method stored in the Object "object" here? and actually run it?



            
    );

以及按钮中的代码 sn-p:

CustomButton button = new CustomButton();

button.CustomButtonListener(def());





public void def()

    String a = "lambda!";

            System.out.print("a");




【问题讨论】:

通过使用 Java 中现有的 lambda 功能?我不认为我理解你的问题。您能否发布到目前为止您拥有的代码以及运行它时会发生什么以及您预期会发生什么? 你是在暗示代码不是纯Java吗?为什么不呢? Lambda expressionsJava 8 中引入,如果可以使用版本>7,则可以使用它们。 @SmartCodeNoBugs 为什么不直接看一下 ActionListener、ActionEvent 和 JButton 的文档和源代码?并阅读有关 lambdas 的文档? docs.oracle.com/javase/tutorial/java/javaOO/… JButton、ActionListener 和 ActionEvent 存在,就像它们在 Java 8 中一样,从 Java 2 开始。没有任何改变。 Lambda 只是一种创建接口实例的新方法。 【参考方案1】:

如果我没有误解你的问题,你的语法已经是正确的。

public static void main() 
    ...
    jButton.addActionListener(e -> myListener());
    ...

...
public void myListener()
    dosomething();

这是它的简写:

public static void main() 
    ...
    MyListener myListener = new MyListener();
    jButton.addActionListener(myListener);
    ...


public class MyListener implements ActionListener 
    @Override
    public void actionPerformed(ActionEvent e) 
        dosomething();
    

更多信息可以参考this。

有关更详细的解释,您还可以参考 Lambda 类型推断部分下的this。

【讨论】:

【参考方案2】:

Lambda 表达式 是在 Java 8 中引入的。如果您使用的是较早的 Java 版本,则可以使用类和接口实现相同的模式。只需创建一个实现ActionListener 接口和相应方法的类。您可以通过使用匿名类来缩短它。然后创建此类的一个实例并将其传递给addActionListener 方法。或多或少,lambda 的作用完全相同(不过,它们的性能可能会有所提高)。

这是一个例子:

public static void main() 
    ...
    MyListener myListener = new MyListener();
    jButton.addActionListener(myListener);
    ...


public class MyListener implements ActionListener 
    @Override
    public void actionPerformed(ActionEvent e) 
        System.out.println("Triggered!");
    

还有匿名类

public static void main() 
    ...
    jButton.addActionListener(new ActionListener() 
        @Override
        public void actionPerformed(ActionEvent e) 
            System.out.println("Triggered!");
        
    );
    ...

【讨论】:

感谢您的快速解释......但不幸的是我仍然不明白。我如何想出像这样的 lambda 模式:jButton.addActionListener(ae -> callAnyMethod());从您提供的代码中? Java 8下面你根本不能使用Lambda表达式,因为Java没有这个语言特性。您不能创建如此短的表达式,并且需要使用实现类(因为它最初是由语言设计者打算的)。然而 Lambda 表达式等价于类风格,但写起来要短得多。 如果没有 lambda,我能想象的最短的事情是使用匿名 classes,如上所示,或者缩短一行而不将其保存在变量中:jButton.addActionListener(new ActionListener() public void actionPerformed(ActionEvent e) System.out.println("Triggered!");); 嗯,谢谢,但我真正想要的是:jButton.addCustomListener(callAnyMethod());我的 CustomListener 类是一个库,用户只需要像上面一样设置 CustomListener 并且 callAnyMethod 可以是用户自己创建的方法,并且只像 lambda 那样传递它,例如: public void passParameter() // 做某事现在我们只用一行代码调用这个方法:jButton.addCustomListener(passParameter()); 在明确表示要避免使用 lambda 习语之后,您得到了答案然后抱怨它不像 lambdas。你应该选择一个或另一个,因为它不会同时双向。你得到了一个阅读教程中的 lambdas 的建议。是你做的吗?按照您的要求替换任何给定方法的方法是在方法参数所需的接口的实现中提供该方法。那是老式的 Java。 (新派 Java 仍然是“纯粹的”,所以这是一个错误的术语选择。)【参考方案3】:

您必须确定您的听众使用哪个Interface 并声明一个匿名类。

假设jButton.addActionListener(...) 等待ActionListener

jButton.addActionListener(new ActionListener() 
    @Override
    public void actionPerformed(ActionEvent e) 
        callAnyMethod();
    
);

在 Java 8 中原生实现的 Lambda 是另一种访问方法和 Functional Interfaces 的方式,以一种简单易读的方式。编译器会自动检测它应该使用什么并调用它。


我不了解您的项目,但如果您负担得起,学习如何使用 Lambdas(和 Streams)将大大提高您的工作效率,使您的代码更简单、更易读且不易出错。

【讨论】:

addActionListener() 采用 ActionListener 类型的参数,而不是 Runnable 您不必声明匿名类来执行此操作,如果您愿意,可以使用ActionListener 的命名子类。而且该技术适用于采用可扩展类的方法,而不仅仅是接口参数。

以上是关于如何在 ActionListener 中创建类似 lambda 的模式的主要内容,如果未能解决你的问题,请参考以下文章

如何在 postgresql 中创建只读视图,类似于 oracle?

如何在 Qt 中创建类似 Textmate 的侧面板

如何在 SQL Server [2005] 中创建类似于 .dbo 的架构

如何在 Kivy 或 KivyMD 中创建类似快照的按钮?

如何在 Swift 中创建类似 Android 的共享选项 [重复]

如何在 R 中创建类似 swirl() 的函数?