首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java Swing 模態對話框顯示後 `ad.setVisible(false)` 空指針:變量賦值時機問題

     編輯:程式設計綜合問答

現象

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
        }
    }
}

正確做法:用 `this` 或 `AddDialog.this`

// 對話框內部關閉自身
AddDialog.this.setVisible(false); // 或 this.setVisible(false)
// 或
dispose(); // 釋放資源並關閉,推薦

為什麼 `this` 沒事?

  • this 指向**正在執行構造函數的對象實例**,構造函數執行期間 `this` 已經存在
  • 外層變量 `ad` 是**引用**,賦值發生在 `new AddDialog()` 表達式**返回後**
  • 模態對話框 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),切勿依賴外層尚未賦值的引用變量。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved