-1

First, some context. I'm just getting back into Java after a 2-year long break that I spent almost exclusively scripting in Python at work. Unfortunately, I'm a lot rustier than I would have expected. As a sort of refresher, I've been working on building a GUI for a simple program I wrote a while back that I use on a daily basis at work. I've been using a lot of the tutorials and sample code on Oracle's website to help fill in the gaps in my memory of Java. Right now, I'm working on creating a custom dialog class that can accept, validate, and return user input. I used this sample code on the Oracle site as my jumping off point. Most of the code has been really helpful, but I couldn't help but notice a this leak in the constructor for the class, which seems odd for sample code provided by Oracle. (code below)

/** 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);**
}

I will admit that I first did not know what the "leaking this in constructor" warning in NetBeans meant, but I have since read this question, which was helpful; however, I'm still unsure of how I could go about registering those event handlers any other way. I'm not substantially concerned about actual consequences that the leaking this might cause in my program, but I would like to know if there is another way to go about this. Considering it was done this way in the sample code for an Oracle Java tutorial leads me to believe that there isn't another obvious way to go about it.

Note: my question is not "why is leaking this in the constructor bad practice" nor is it "what are the consequences of leaking this in the constructor." I am also not asking why my IDE (NetBeans) is giving me this warning. My question is concerned more so with what an alternative way of registering event handlers within the class itself would be without leaking this.

wjjd225
  • 57
  • 11

1 Answers1

2

As suggested in your aforementioned post, you could introduce a static creation method, make the constructor private and move the addXxxListener() calls to the static method.

But I'd leave the code as it is, maybe with an @SuppressWarnings annotation and a warning comment that the addXxxListener() calls should stay at the end of the constructor.

After all, it's a warning on a potential problem where the compiler lacks the intelligence to see that the instance is completely finished at that point (at least, in a single-threaded sense - multi-thread safety is a different concern) and all the other classes getting to see the object prematurely will effectively see a finished version.

Ralf Kleberhoff
  • 6,990
  • 1
  • 13
  • 7
  • A static creation method makes sense. Thanks for the advice. – wjjd225 Aug 04 '17 at 14:38
  • I am slightly confused about what's going on behind the scenes as far as those addXxxListener() calls go when they're in the constructor. How is that the actual addXxxListener() method isn't executed until the constructor is finished? – wjjd225 Aug 04 '17 at 14:48
  • 1
    It is executed before the constructor finishes - it's called from inside the constructor. But that doesn't hurt because the reference is already valid and won't change any more. The potential problem is that the fields of the instance (and other status) might not yet be completely filled to the finished state. The addXxxListener() calls just store the reference somewhere for later use, to be called when the event occurs. – Ralf Kleberhoff Aug 04 '17 at 17:12