2017-08-04 55 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()调用只是将引用存储在某处供以后使用,以便在事件发生时调用。 –