为什么在使用方法引用时动作侦听器会给出不同的结果?
Why does an action listener gives different result when using method reference?
今天,我遇到了一个奇怪的(对我来说)行为,我检查了它。我确实阅读了很多关于方法引用和 lambda 之间的区别的主题,但我无法将它与我的示例联系起来。考虑以下 class:
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);
}
}
当你 运行 它和组合框一起玩时,你会得到 "normal" 输出,如:
Index: 3 Index: 1 Index: 4 Index: 0
但是如果我改变我使用方法引用添加侦听器的方式:
comboBox.addActionListener(new ChangedIndexEvent(comboBox.getSelectedIndex())::printSelectedIndex);
输出将是:
Index: 0 Index: 0 Index: 0
我的问题是,为什么总是0?
我的意思是,如果我 comboBox.setSelectedIndex(2);
它总是 return 2 我猜它 return 是 "initial" 值。但是方法引用不和lambda表达式一样吗?
方法引用是对单个方法的引用。如果(如您的情况)它是对特定实例的实例方法的引用,它将始终为同一实例执行。
因此,new ChangedIndexEvent(comboBox.getSelectedIndex())
被评估一次以创建其方法被 new ChangedIndexEvent(comboBox.getSelectedIndex())::printSelectedIndex
引用的实例。
因此,当您使用该方法引用时,所选索引永远不会改变。
另一方面,当您使用 lambda 表达式 event -> {new ChangedIndexEvent(comboBox.getSelectedIndex()).printSelectedIndex(event);}
时,每次执行此表达式实现的方法时,都会创建一个新的 ChangedIndexEvent
实例,具有不同的选定索引.
今天,我遇到了一个奇怪的(对我来说)行为,我检查了它。我确实阅读了很多关于方法引用和 lambda 之间的区别的主题,但我无法将它与我的示例联系起来。考虑以下 class:
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);
}
}
当你 运行 它和组合框一起玩时,你会得到 "normal" 输出,如:
Index: 3 Index: 1 Index: 4 Index: 0
但是如果我改变我使用方法引用添加侦听器的方式:
comboBox.addActionListener(new ChangedIndexEvent(comboBox.getSelectedIndex())::printSelectedIndex);
输出将是:
Index: 0 Index: 0 Index: 0
我的问题是,为什么总是0?
我的意思是,如果我 comboBox.setSelectedIndex(2);
它总是 return 2 我猜它 return 是 "initial" 值。但是方法引用不和lambda表达式一样吗?
方法引用是对单个方法的引用。如果(如您的情况)它是对特定实例的实例方法的引用,它将始终为同一实例执行。
因此,new ChangedIndexEvent(comboBox.getSelectedIndex())
被评估一次以创建其方法被 new ChangedIndexEvent(comboBox.getSelectedIndex())::printSelectedIndex
引用的实例。
因此,当您使用该方法引用时,所选索引永远不会改变。
另一方面,当您使用 lambda 表达式 event -> {new ChangedIndexEvent(comboBox.getSelectedIndex()).printSelectedIndex(event);}
时,每次执行此表达式实现的方法时,都会创建一个新的 ChangedIndexEvent
实例,具有不同的选定索引.