The specific use where I thought of this problem is as follows, but it's much more generalized.
I have a custom JFrame
class which also serves as an ActionListener
for its components. So my constructor looks something like the following:
private JButton myButton;
public MyCustomFrame() {
super();
myButton.addActionListener(this);
// ... more stuff
}
My question is, how does this actually work behind the scenes? If the constructor is what "creates" the object which is referenced by this
, how can I use this
before the constructor has returned? The code compiles and works perfectly fine (as far as I can tell), so the object must already "exist" in some sense, but I'm concerned that this may cause unforeseen issues. Is there any danger in passing a "partially constructed" reference to addActionListener()
(or just performing any logic with it in general)? Or is there some behind-the-curtain magic happening that keeps me safe?
For example, what about things which don't have default values and must be supplied by the constructor? If I have private final String SOME_VALUE;
declared, I understand that this should default to null
, but the object isn't supposed to be fully formed until the constant is supplied a value within the constructor. So would the reference, despite being final, possibly have changing values?
That Java Language Specification specifies the steps of instance creation
So by the time the constructor (which is a method) is invoked, your instance exists with default values.
For
final
fields, it appears those are defaulted as well if you try to access them. For examplewill print 0. I'll be right back with the JLS entry if I can find it.
I couldn't find anything more specific then what is above. Maybe in 4.12.4.
final
VariablesYou can take to mean that default initialization puts the value to 0 or
null
and the assignment changes it.Don't escape this from the constructor because if another thread read variables of the instance which construction hasn't finished yet, the thread may read unexpected value.
A example is below.
This program may show a value other than 10 from Java Memory Model specification.
You are absolutely right, that is a bad thing to do as
this
may only be partially initialized at the time you use it.This is why many compilers will give a warning about doing it.
this
does actually exist before the constructor finishes. However, allowing a reference tothis
to escape your object before the constructor is complete can present a danger.What if you passed your
this
reference to a method that assumes your object is fully formed and ready to go? Maybe this is fine in the case of your object, but in many cases, this could be dangerous. Allowing other methods access to an object before it is ready to be used would present a serious threat to your program being able to run reliably.Once you call your constructor, your object already exists from the start, and you're just populating it with values.
The danger of this comes if the method you're passing your object to tries to use a value that you haven't declared yet in your constructor.
You also want to avoid having your constructor(and other methods for that matter) behave in such a way that the user of the constructor wouldn't expect.
If the person instantiating your object doesn't have a reason to expect the constructor to automatically bind that object to a button, than maybe you shouldn't do that.