【问题标题】:Using method references使用方法引用
【发布时间】:2014-10-11 21:40:52
【问题描述】:

我有一个JButton称为saveButton,并希望它在单击时调用save 方法。当然,我们可以使用旧方法来做到这一点:

    saveButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            save();
        }
    });

但是今天我想使用 Java 8 的新特性,比如方法引用。为什么

    saveButton.addActionListener(this::save);

不工作?使用方法引用是如何做到的?

【问题讨论】:

  • addActionListener 期望什么作为参数? Read the tutorial on method references.
  • 您的save 方法与actionPerformed 的签名不同。因此它不能被解释为ActionListener 的SMI 的实现。您需要阅读有关 Java 8 中方法引用的更多信息。
  • @BoristheSpider 谢谢。我刚刚将save的签名更改为private void save(ActionEvent e)。现在可以了。

标签: java actionlistener java-8 method-reference


【解决方案1】:

方法actionPerformed(ActionEvent e) 需要单个参数e。如果您想使用方法引用,您的方法必须具有相同的签名。

private void myActionPerformed(ActionEvent e) {
    save();
}

然后你可以使用方法参考:

saveButton.addActionListener(this::myActionPerformed);

或者你可以使用 lambda 代替(注意 e 参数):

saveButton.addActionListener(e -> save());

【讨论】:

  • 严格来说,这不是方法参考,而是 lambda - 它实际上并没有回答 OP 的问题...
  • 你是对的。有两个问题Why does not work?How is it done using method references?。你已经回答了cmets中的第二个问题,所以我只回答了第一个。
  • 在下面查看我的替代答案
【解决方案2】:

您可以使用 lambda:

saveButton.addActionListener((ActionEvent e) -> save());

这是可以做到的,因为 ActionListener 是一个功能接口(即只有一个方法)。功能接口是任何只包含一个抽象方法的接口。 Lambda 是调用的简写。

除了使用 Lambda,您还可以通过让您的类实现 有问题的接口(或其他带有实例变量的类)。这是一个完整的例子:

public class Scratch implements ActionListener {

    static JButton saveButton = new JButton();

    public void save(){};

    public void contrivedExampleMethod() {

        saveButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                save();
            }
        });

        // This works regarless of whether or not this class
        // implements ActionListener, LAMBDA VERSION
        saveButton.addActionListener((ActionEvent e) -> save());

        // For this to work we must ensure they match
        // hence this can be done, METHOD REFERENCE VERSION
        saveButton.addActionListener(this::actionPerformed);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        save();
    }
}

这当然只是一个人为的例子,但是假设您传递正确的方法或使用 Lambdas 创建正确的内部类(类似)实现,它可以通过任何一种方式完成。由于动态特性,我认为 lambda 方式在实现您想要的方面更有效。毕竟这就是他们在那里的原因。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-07-11
    • 2016-02-08
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多