我们必须显式地告诉程序在窗口关闭时应该做什么,最常见的需求是完全退出应用程序。

下面我将从最推荐的方法开始,逐步介绍其他情况和相关知识点。
最推荐的方法:使用 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
这是最直接、最常用的方法,它告诉窗口,当用户尝试关闭窗口时,应该执行一个“JVM退出”的操作。
代码示例:
import javax.swing.JFrame;
public class SimpleWindowCloseExample {
public static void main(String[] args) {
// 1. 创建一个 JFrame 窗口实例
JFrame frame = new JFrame("我的 Swing 窗口");
// 2. 设置窗口关闭时的默认操作
// 这是最关键的一行代码!
// 它告诉程序,当点击关闭按钮时,调用 System.exit(0) 来终止 Java 虚拟机。
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 3. 设置窗口大小
frame.setSize(400, 300);
// 4. 设置窗口在屏幕上可见
frame.setVisible(true);
// 5. 可选:设置窗口关闭时无法被调整大小
// frame.setResizable(false);
}
}
代码解释:

JFrame.EXIT_ON_CLOSE:这是一个int类型的常量,其值为3,它被预定义为关闭窗口时终止应用程序。- 当你运行这段代码并点击窗口的 "X" 按钮时,整个 Java 程序会立即终止。
其他可用的关闭操作
setDefaultCloseOperation 方法可以接收以下几个预定义的常量,每种常量对应一种不同的行为:
| 常量 | 值 | 描述 |
|---|---|---|
JFrame.DO_NOTHING_ON_CLOSE |
0 |
什么都不做,窗口会保持打开状态,你需要通过编程方式(一个“退出”按钮的点击事件)来手动关闭它。 |
JFrame.HIDE_ON_CLOSE |
1 |
隐藏窗口,窗口会从屏幕上消失,但窗口对象仍然存在,程序的后台线程继续运行,这是默认行为。 |
JFrame.DISPOSE_ON_CLOSE |
2 |
销毁窗口,窗口会被销毁并释放其占用的系统资源(如内存),如果这是最后一个显示的窗口,程序可能会继续运行,但没有可见的 GUI 界面。 |
JFrame.EXIT_ON_CLOSE |
3 |
退出程序,调用 System.exit(0) 来终止整个应用程序。这是桌面应用程序最常用的选项。 |
示例:使用 DISPOSE_ON_CLOSE
如果你希望关闭一个窗口后,只销毁它而不退出整个程序(一个多文档界面MDI的应用程序),可以使用 DISPOSE_ON_CLOSE。
import javax.swing.JFrame;
import javax.swing.JLabel;
public class DisposeOnCloseExample {
public static void main(String[] args) {
JFrame frame = new JFrame("DISPOSE_ON_CLOSE 示例");
frame.add(new JLabel("点击关闭按钮,此窗口将被销毁,但程序不会退出。"));
frame.setSize(350, 200);
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // 使用 DISPOSE_ON_CLOSE
frame.setVisible(true);
// 为了演示程序没有退出,我们可以再创建一个窗口
JFrame anotherFrame = new JFrame("另一个窗口");
anotherFrame.add(new JLabel("这个窗口仍然可以操作。"));
anotherFrame.setSize(350, 200);
anotherFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 这个窗口关闭时才退出程序
anotherFrame.setLocationRelativeTo(frame); // 让它显示在第一个窗口旁边
anotherFrame.setVisible(true);
}
}
高级用法:添加窗口监听器(WindowListener)
当你需要执行更复杂的关闭逻辑时,
- 在关闭前弹出确认对话框:“您确定要退出吗?”
- 保存未保存的数据到文件。
- 关闭网络连接或数据库连接。
这时,你就需要使用 WindowListener 接口。

WindowListener 接口有多个方法,但最常用的是 windowClosing(WindowEvent e),这个方法会在窗口即将关闭时被调用。
代码示例:
import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
public class WindowListenerExample {
public static void main(String[] args) {
JFrame frame = new JFrame("窗口监听器示例");
// 使用匿名内部类来创建一个 WindowAdapter
// WindowAdapter 是 WindowListener 的一个方便实现,我们只需要重写需要的方法即可
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// 弹出一个确认对话框
int option = JOptionPane.showConfirmDialog(
frame,
"您确定要退出程序吗?",
"确认退出",
JOptionPane.YES_NO_OPTION,
JOptionPane.WARNING_MESSAGE
);
// 如果用户点击了 "是"
if (option == JOptionPane.YES_OPTION) {
// 执行退出操作
System.exit(0);
}
// 如果用户点击了 "否",或者关闭了对话框,则什么都不做,窗口保持打开状态
}
});
frame.add(new JLabel("尝试关闭窗口,会看到一个确认对话框。"));
frame.setSize(400, 300);
// 注意:这里我们没有设置默认关闭操作,因为监听器会接管它
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 如果加上这句,监听器中的 System.exit(0) 就会执行两次
frame.setVisible(true);
}
}
代码解释:
frame.addWindowListener(...): 为窗口添加一个窗口监听器。new WindowAdapter():WindowListener接口有7个方法,为了方便,Swing 提供了WindowAdapter这个适配器类,它实现了所有方法,但方法体都是空的,我们只需要继承它并重写我们关心的方法(这里是windowClosing),而不用实现所有7个方法。windowClosing(WindowEvent e): 当用户点击关闭按钮时,这个方法被触发。JOptionPane.showConfirmDialog(...): 显示一个标准的确认对话框。System.exit(0): 只有在用户确认后,才真正退出程序。
总结与最佳实践
| 场景 | 推荐方法 | 说明 |
|---|---|---|
| 简单的桌面应用程序 | frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); |
这是最简单、最直接的方式,确保程序能正确退出。 |
| 需要自定义关闭逻辑(如保存数据、弹出确认框) | frame.addWindowListener(new WindowAdapter() { ... }); |
在 windowClosing 方法中编写你的逻辑,并在最后决定是否调用 System.exit(0)。 |
| 隐藏窗口但不销毁 | frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE); |
用于系统托盘功能,点击关闭按钮后窗口隐藏到托盘。 |
| 创建一个非顶级窗口(如MDI子窗口) | frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); |
关闭单个窗口,释放其资源,但不影响其他窗口或主程序。 |
核心要点:
- 永远不要依赖默认行为,默认的
HIDE_ON_CLOSE会让你的程序看起来已经退出了,但实际上可能还在后台运行。 - 对于大多数独立的 Swing 应用程序,
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)是你的首选。 - 当你需要执行“关闭前”的任何操作时,
WindowListener是你的不二之选。
