Reputation: 1863
Does the this reference escape during construction problem (as called by Brian Goetz and others in Java Concurrency in Practice) affect single-threaded programs or just multi-threaded programs? I mean, is it OK to let the this reference escape during construction if my classes aren't supposed to be thread-safe anyway?
EDIT: For example, here:
public class ThisEscape {
public ThisEscape(EventSource source) {
source.registerListener(
new EventListener() {
public void onEvent(Event e) {
doSomething(e);
}
});
}
}
EDIT2: The motivation for my question is that the plugin WindowBuilder for Eclipse creates (or seems to create...) the action listeners in a JFrame's constructor and by default passing anonymous classes to those, thereby allowing the this reference to escape...
Upvotes: 3
Views: 159
Reputation: 194
Don't do it. Letting a reference escape before construction can cause unspecified behavior. Use the static factory pattern and let your worries rest, multiple threads or not
In your example it would look like this:
public class ThisEscape{
private final EventListener listener;
private ThisEscape(){
listener = new EventListener();
}
public static public ThisEscape makeEscape(EventSource source){
ThisEscape e = new ThisEscape();
source.registerListener(e.listener);
return e;
}
private class EventListener{
public void onEvent(Event e){
doSomething(e);
}
}
}
Obviously the static factory doesn't allow for seamless class extension, but in my experience this is not generally a problem, even if a few factory methods need to be made.
This code would be thread safe in regards to construction; be sure to mind that the rest of your class is thread safe.
Upvotes: 2
Reputation: 8586
Allowing the "this" reference to escape isn't necessarily going to cause problems. It can work out okay, but it's completely dependent on what the other code does with it.
So why is it a best practice to not leak this in the constructor? What if EventSource were to send a "now connected" event immediately from within the register function. What happens? doSomething() gets called (and mind you, you're still mid-constructor and may not be done initializing the object). It entirely depends on what the method does, but one of the following is true:
But, you say, it doesn't send that event. So you're okay, right? Well, until someone else changes it, and it starts sending something like that, and then you spontaneously break without a direct change to your code.
Short form: avoid doing that if you can; it can cause headaches. If you absolutely must for some reason, take care that you initialize everything that you can before leaking it, and take great care to understand what's going to happen, and realize that there's potential for future trouble.
Upvotes: 2
Reputation: 533780
Generally speaking you shouldn't try to use your object until it is fully constructed. If you pass the object to some other code before it has been fully initialised this can lead to confusing results, unless you are very careful. Even in single threaded programs.
That said, sometimes it is not a problem esp if you know the object will not be used until later.
Upvotes: 5