deinocheirus
deinocheirus

Reputation: 1863

this reference escape single-threaded programs

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

Answers (3)

electroCutie
electroCutie

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

James
James

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:

  1. everything you need in doSomething is initialized before the listener is registered, and things work out.
  2. something is null, and you ignore it, leading to unexpected results
  3. something blows up as a result of something being null when it shouldn't be (NPE or similar).

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

Peter Lawrey
Peter Lawrey

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

Related Questions