2017-08-04 4 views
-1

まず、いくつかのコンテキスト。 2年間の長い休憩のあいだにJavaに戻ってきました。私は仕事場でPythonでスクリプトを作成するだけでした。残念ながら、私は予想以上に錆びています。一種のリフレッシャーとして、私は仕事中に日常的に使っている簡単なプログラムのGUIを構築しています。私は、OracleのWebサイトで多くのチュートリアルとサンプル・コードを使用して、Javaの記憶の隙間を埋めるのを助けてきました。今、私は、ユーザーの入力を受け入れ、検証し、返すカスタムダイアログクラスを作成しています。私はthisサンプルコードを私の飛び降りるポイントとしてOracleのサイトで使用しました。コードの大半は本当に役に立ちましたが、私は助けができませんでしたが、クラスのコンストラクタにthisのリークがあることに気付きました。 (以下のコード)OracleのJavaチュートリアルのコンストラクタで 'this'をリークする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()呼び出しは、イベントが発生したときに後で使用するために参照をどこかに格納するだけです。 –

関連する問題