为什么在使用方法引用时动作侦听器会给出不同的结果?

时间:2019-07-03 11:42:33

标签: java swing lambda method-reference

今天,我遇到了一种奇怪的行为(对我而言),我进行了检查。我确实阅读了很多有关方法引用和lambda之间差异的主题,但是我无法将其与示例联系起来。考虑以下课程:

public class TestFrame extends JFrame {
    private static final long serialVersionUID = 1L;
    private JComboBox<String> comboBox;

    public TestFrame() {
        super("test");
        setLayout(new FlowLayout());
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        comboBox = new JComboBox<>(new String[] { "hello", "world", "hi", "stack", "overflow" });
        comboBox.addActionListener(event -> {
            new ChangedIndexEvent(comboBox.getSelectedIndex()).printSelectedIndex(event);
        });
        add(comboBox);
        setLocationRelativeTo(null);
        setSize(200, 200);
        setVisible(true);
    }

    private class ChangedIndexEvent {
        private int index;

        public ChangedIndexEvent(int index) {
            this.index = index;
        }

        private void printSelectedIndex(ActionEvent event) {
            System.out.println("Index: " + index);
        }

    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(TestFrame::new);
    }

}

当您运行它并在组合框上播放一下时,您将获得“正常”输出,例如:

  

索引:3索引:1索引:4索引:0

但是,如果我改变了使用方法引用添加侦听器的方式:

comboBox.addActionListener(new ChangedIndexEvent(comboBox.getSelectedIndex())::printSelectedIndex);

输出将是:

  

索引:0索引:0索引:0

我的问题是,为什么总是0?

我的意思是,如果我comboBox.setSelectedIndex(2);总是返回2,我猜它返回的是“初始”值。但是方法引用与lambda表达式不同吗?

1 个答案:

答案 0 :(得分:1)

方法引用是对单个方法的引用。而且,如果(如您的情况)它是对特定实例的实例方法的引用,则它将始终针对同一实例执行。

因此,new ChangedIndexEvent(comboBox.getSelectedIndex())被评估一次以创建实例,该实例的方法被new ChangedIndexEvent(comboBox.getSelectedIndex())::printSelectedIndex引用。

因此,当您使用该方法引用时,所选索引永远不会更改。

另一方面,当您使用lambda表达式event -> {new ChangedIndexEvent(comboBox.getSelectedIndex()).printSelectedIndex(event);}时,每次执行此表达式实现的方法时,它都会创建一个ChangedIndexEvent的新实例,该实例具有不同的选定索引。 / p>