0

Today, i came across a strange (for me) behavior and i checked it. I did read a bunch of topics about the difference between a method reference and a lambda, but i cannot connect it with my example. Consider the following 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);
    }

}

When you run it and you play a bit with the combo box you will get a "normal" output like:

Index: 3 Index: 1 Index: 4 Index: 0

But if i change the way i add the listener using a method reference:

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

The output will be:

Index: 0 Index: 0 Index: 0

My question is, why is it always 0?

I mean, if i comboBox.setSelectedIndex(2); it will always return 2 which i guess it returns the "initial" value. But isn't a method reference the same as the lambda expression?

George Z.
  • 6,643
  • 4
  • 27
  • 47

1 Answers1

1

A method reference is a reference to a single method. And if (as in your case) it is a reference to an instance method of a specific instance, it will always be executed for the same instance.

Hence, new ChangedIndexEvent(comboBox.getSelectedIndex()) is evaluated once to create the instance whose method is referenced by new ChangedIndexEvent(comboBox.getSelectedIndex())::printSelectedIndex.

Hence the selected index never changes when you use that method reference.

On the other hand, when you use the lambda expression event -> {new ChangedIndexEvent(comboBox.getSelectedIndex()).printSelectedIndex(event);}, each time the method implemented by this expression is executed, it creates a new instance of ChangedIndexEvent, having a different selected index.

Eran
  • 387,369
  • 54
  • 702
  • 768