兩種寫法功能完全一致,適用場景不同。
public class ActionListenerTest {
public static void main(String[] args) {
JFrame frame = new JFrame("Button Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JButton btnClose = new JButton("Close the Frame"); // 必須 final
btnClose.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == btnClose) { // 或 e.getSource().equals(btnClose)
System.exit(0);
}
}
});
frame.add(btnClose);
frame.pack();
frame.setVisible(true);
}
}
關鍵點:
public class ButtonFrame extends JFrame implements ActionListener {
private JButton btnClose;
public ButtonFrame() {
super("ButtonFrame Test");
btnClose = new JButton("Close the Frame in ButtonFrame");
btnClose.addActionListener(this); // this 指向當前實現類
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(btnClose);
pack();
setVisible(true);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == btnClose) {
System.exit(0);
}
}
public static void main(String[] args) {
new ButtonFrame(); // 僅需實例化
}
}
優勢:
// 模式一簡化
btnClose.addActionListener(e -> {
if (e.getSource() == btnClose) System.exit(0);
});
// 模式二簡化 (構造器中)
btnClose.addActionListener(this::handleClose);
private void handleClose(ActionEvent e) {
if (e.getSource() == btnClose) System.exit(0);
}
Lambda 實質是函數式介面 `ActionListener` 的實例,碼更簡潔、語義更清晰。
| 問題 | 原因 | 解決 |
|---|---|---|
| 匿名類中訪問區域變數報錯 | 非 final/效果上 final | 加 `final` 或改為成員變數 |
| 事件不觸發 | 未調用 `addActionListener` | 檢查註冊代碼執行順序 |
| 多按鈕共用 listener 邏輯混亂 | 用 `getSource()` 判斷 | 改用 `setActionCommand("cmd")` + `getActionCommand()` |
| 介面方法非 public | 權限不足 | `public void actionPerformed(...)` |
兩種模式本質相同,皆是「註冊回調」。理解 `final` 限制、Lambda 語法糖、介面導向設計,才能在 Swing 事件驅動編程中遊刃有餘。