3
I was reading about Ambdas and out of curiosity, I wanted to know why it is not allowed to use when the class/ interface has more than one method, which ends up forcing us to do things like below:
component.addMouseListener(new MouseListener() {
@Override
public void mouseReleased(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mousePressed(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseExited(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseEntered(MouseEvent e) {
// TODO Auto-generated method stub
}
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
}
});
Researching, I found that question on Soen about the doubt, but I ended up encountering a solution that circumvents this restriction, as can be seen in this answer:
// note the absence of mouseClicked… interface ClickedListener extends MouseListener { @Override public default void mouseEntered(MouseEvent e) {} @Override public default void mouseExited(MouseEvent e) {} @Override public default void mousePressed(MouseEvent e) {} @Override public default void mouseReleased(MouseEvent e) {} }
You need to define such a helper interface only Once.
Now you can add a Listener for click-Events on a Component c like this:
c.addMouseListener((ClickedListener)(e)->System.out.println("Clicked!"));
I took a test and I really saw that it works:
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
public class MouseListenerLambdaTest {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
new MouseListenerLambdaTest();
});
}
public MouseListenerLambdaTest() {
initComponents();
}
private void initComponents() {
JFrame f = new JFrame();
f.setResizable(false);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setPreferredSize(new Dimension(200, 120));
JPanel contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
f.setContentPane(contentPane);
contentPane.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
JLabel label = new JLabel();
contentPane.add(label);
contentPane.addMouseListener((MouseListenerHelper) (e) -> label.setText("Clicked"));
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
interface MouseListenerHelper extends MouseListener {
@Override
public default void mouseEntered(MouseEvent e) {
}
@Override
public default void mouseExited(MouseEvent e) {
}
@Override
public default void mousePressed(MouseEvent e) {
}
@Override
public default void mouseReleased(MouseEvent e) {
}
}
}
To be executed:
How was it possible to circumvent the requirement that the interface MouseListener
imposes in this code? How does this function know that it is the method MouseClicked
if not implemented it was?
Note: I am aware of the existence of Adapters, and in this case could simply use the class
MouseAdapter
, but the use of Mouselistener was only illustrative, as not all java listeners have an Adapter equivalent.
Related: What are functional interfaces?
– user28595