6

I started reading Java Concurrency in Practice and I came across the following example (this is a negative example - shows bad practice):

public class ThisEscape {
    public ThisEscape(EventSource source) {
        source.registerListener(new EventListener() {
            public void onEvent(Event e) {
                doSomething(e);
            }
        });
    }
}

The author in the book writes:

When ThisEscape publishes the EventListener, it implicitly publishes the enclosing ThisEscape instance as well, because inner class instances contain a hidden reference to the enclosing instance.

When I think about the usage of such code, I could do something like so:

EventSource eventSource = new EventSource();
ThisEscape thisEscape = new ThisEscape(eventSource);

and I can get the reference to the registered EventListener, but what does it mean that I could obtain the reference to the enclosing ThisEscape instance?

Could someone give me an example of such a behaviour? What is the use case?

5
  • 1
    Probably this could be an example: stackoverflow.com/a/1084124/4563745 Commented Jun 18, 2017 at 11:11
  • Ok, this is nice use case, but I still don't understand what is wrong with such escaping reference - even if I'd do ThisEscape.this.doSomething(); from within anonymous implementation, 'this' still stays visible within ThisEscape only. Commented Jun 18, 2017 at 11:26
  • The event source can send events before ThisEscape constructor has finished. The events will be processed with the object in an unpredictable state. Commented Jun 18, 2017 at 11:34
  • Possible duplicate of Allowing the this reference to escape Commented Jun 18, 2017 at 12:03
  • I found another great explanation for the same issue: stackoverflow.com/questions/28676796/… Commented Jun 18, 2017 at 19:40

2 Answers 2

1

The problem with escaping this references is that code in other threads might start interacting with the object before the constructor is finished constructing it.

Consider this example:

public class ThisEscape
{
    Foo foo;
    public ThisEscape(EventSource source) {
        source.registerListener(new EventListener()
        {
            public void onEvent(Event e) {
                doSomething(e);
            }
        });

        // Possible Thread Context switch

        // More important initialization
        foo = new Foo();
    }

    public void doSomething(Event e) {
        // Might throw NullPointerException, by being invoked
        // through the EventListener before foo is initialized
        foo.bar();
    }
}
Sign up to request clarification or add additional context in comments.

Comments

0

I also encounter this problem.Then I lookup the whole code from the official site.You will understand naturally.The whole ThisEscape class looks like this:

package net.jcip.examples;

/**
 * ThisEscape
 * <p/>
 * Implicitly allowing the this reference to escape
 *
 * @author Brian Goetz and Tim Peierls
 */
public class ThisEscape {
    public ThisEscape(EventSource source) {
        source.registerListener(new EventListener() {
            public void onEvent(Event e) {
                doSomething(e);
            }
        });
    }

    void doSomething(Event e) {
    }


    interface EventSource {
        void registerListener(EventListener e);
    }

    interface EventListener {
        void onEvent(Event e);
    }

    interface Event {
    }
}

Notice that the doSomething method is part of the ThisEscape class, which means that another thread could potentially access the object through the this reference before the object has finished constructing itself.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.