AddDialog 構造函數末尾 this.setVisible(true) 顯示模態對話框,此時構造函數**阻塞**,直到對話框關閉。外層調用處 ad = new AddDialog() 尚未完成賦值,`ad` 仍為 `null`。若在對話框內部按鈕點擊事件中用 `ad.setVisible(false)` 即拋 NPE。
// 外層調用
if (e.getSource() == jb1) {
ad = new AddDialog(); // 這裡阻塞,直到對話框關閉
// ad 賦值在 new 返回後才發生
}
// 對話框內部按鈕事件
private class AddDialogClick implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == jb1) {
// 業務邏輯...
ad.setVisible(false); // NPE!ad 還是 null
}
}
}
// 對話框內部關閉自身
AddDialog.this.setVisible(false); // 或 this.setVisible(false)
// 或
dispose(); // 釋放資源並關閉,推薦
this 指向**正在執行構造函數的對象實例**,構造函數執行期間 `this` 已經存在setVisible(true) 導致**當前線程阻塞在構造函數內部**,外層賦值語句根本沒執行到private class AddDialog extends JDialog {
public AddDialog(JFrame owner) {
super(owner, "標題", true); // 模態
// 初始化組件、佈局、監聽器...
pack();
setLocationRelativeTo(owner);
setVisible(true); // 阻塞點
}
private class BtnListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == btnOk) {
// 業務校驗...
dispose(); // 關閉並釋放,比 setVisible(false) 更徹底
} else if (e.getSource() == btnCancel) {
dispose();
}
}
}
}
// 外層調用:無需接收返回值,對話框關閉後繼續執行
new AddDialog(mainFrame);
// 這裡可檢查對話框是否通過某個標誌位判斷用戶點了確定/取消
模態對話框構造函數中調用 `setVisible(true)` 會阻塞調用線程,導致外層引用賦值滯後。 內部關閉自身請用 this.dispose() 或 AddDialog.this.setVisible(false),切勿依賴外層尚未賦值的引用變量。