2017-08-04 46 views
-1

首先,一些背景的構造。在經歷了爲期兩年的長時間休息之後,我正在回到Java中,我幾乎在工作中專門用Python編寫了腳本。不幸的是,我比我所預期的更加生疏。作爲一種進修,我一直致力於爲一個簡單的程序構建一個GUI,我編寫了一個簡單的程序,然後每天在工作中使用。我一直在使用Oracle網站上的很多教程和示例代碼來幫助填補我在Java中的空白。現在,我正在創建一個可以接受,驗證和返回用戶輸入的自定義對話框類。我在Oracle站點上使用this示例代碼作爲我的跳板點。大部分的代碼已經真正有用的,但我不禁注意到在構造函數的類,這似乎很奇怪的Oracle提供示例代碼this泄漏。 (下面的代碼)泄漏「這」在Oracle的Java教程代碼示例爲CustomDialog.java

/** Creates the reusable dialog. */ 
public CustomDialog(Frame aFrame, String aWord, DialogDemo parent) { 
    super(aFrame, true); 
    dd = parent; 

    magicWord = aWord.toUpperCase(); 
    setTitle("Quiz"); 

    textField = new JTextField(10); 

    //Create an array of the text and components to be displayed. 
    String msgString1 = "What was Dr. SEUSS's real last name?"; 
    String msgString2 = "(The answer is \"" + magicWord 
          + "\".)"; 
    Object[] array = {msgString1, msgString2, textField}; 

    //Create an array specifying the number of dialog buttons 
    //and their text. 
    Object[] options = {btnString1, btnString2}; 

    //Create the JOptionPane. 
    optionPane = new JOptionPane(array, 
           JOptionPane.QUESTION_MESSAGE, 
           JOptionPane.YES_NO_OPTION, 
           null, 
           options, 
           options[0]); 

    //Make this dialog display it. 
    setContentPane(optionPane); 

    //Handle window closing correctly. 
    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); 
    addWindowListener(new WindowAdapter() { 
      public void windowClosing(WindowEvent we) { 
      /* 
      * Instead of directly closing the window, 
      * we're going to change the JOptionPane's 
      * value property. 
      */ 
       optionPane.setValue(new Integer(
            JOptionPane.CLOSED_OPTION)); 
     } 
    }); 

    //Ensure the text field always gets the first focus. 
    addComponentListener(new ComponentAdapter() { 
     public void componentShown(ComponentEvent ce) { 
      textField.requestFocusInWindow(); 
     } 
    }); 

    **//Register an event handler that puts the text into the option pane. 
    textField.addActionListener(this); 

    //Register an event handler that reacts to option pane state changes. 
    optionPane.addPropertyChangeListener(this);** 
} 

我承認,我第一次不知道什麼是「在構造函數中泄漏這個」在NetBeans警告的意思,但我後來讀this問題,這是有幫助的;然而,我仍然不確定如何以任何其他方式註冊這些事件處理程序。我基本上不關注的是,泄漏this可能會導致我的程序的實際後果,但我想知道是否有另一種方式去了解這一點。考慮到在Oracle Java教程的示例代碼中這樣做,使我相信沒有另一種明顯的方式去實現它。

注:我的問題是也不是「什麼都在構造函數中泄漏this的後果。」「爲什麼在構造函數中不好的做法泄漏this」我也不問爲什麼我的IDE(NetBeans)給我這個警告。我的問題是什麼註冊事件處理器的另一種方式的類本身將沒有泄漏this而言更是如此。

回答

2

正如您前面提到的建議後,你可能會引入一個靜態的創建方法,使構造私人和移動addXxxListener()調用靜態方法。

但是我會保留代碼原樣,可能帶有@SuppressWarnings註釋和警告註釋,addXxxListener()調用應該停留在構造函數的末尾。

畢竟,這是一個潛在問題的警告,編譯器在缺乏智能的情況下發現實例在該點完全完成(至少,單線程意義上說 - 多線程安全是一個不同的問題)和所有其他類過早查看對象將有效地看到完成的版本。

+0

靜態創建方法是有道理的。感謝您的建議。 – wjjd225

+0

只要addXxxListener()調用在構造函數中時發生,我就會對幕後發生的事情稍感困惑。在構造函數完成之前,實際的addXxxListener()方法是如何執行的? – wjjd225

+1

它在構造函數完成之前執行 - 它從構造函數中調用。但是這並不會造成傷害,因爲參考文獻已經有效,並且不會再改變。潛在的問題是實例的字段(和其他狀態)可能尚未完全填充到完成狀態。 addXxxListener()調用只是將引用存儲在某處供以後使用,以便在事件發生時調用。 –