The implicit this reference escapes in the constructor ---- "Java Concurrent Programming in Practice" 3.2

​​​​​​​​​​​​​​​​​​​​​​​​This is the sample code in the 3.2 release and escape section of "Java Concurrent Programming Practice". I can't understand, how this escapes.

//隐式地使this引用逸出(不要这么做)
public class ThisEscape {
    public ThisEscape(EventSource source){
        source.registerListener(new EventListener() {
            public void onEvent(Event e){
                doSomething(e);
            }
        });
    }
}

The book says that when ThisEscape publishes the EventListener, it also implicitly publishes the ThisEscape instance itself, because the instance of this inner class contains an implicit reference to the ThisEscape instance.

Premise:
Both the inner class and the anonymous inner class can access the domain of the object of the outer class. The reason for this is that when the inner class is constructed, the object this of the outer class is implicitly passed as a parameter to the inner class. Constructor, this work is done by the compiler, he will add this parameter to all the constructors of your inner class, so the anonymous inner class in your example will implicitly pass the object created by ThisEscape to anonymous when you construct ThisEscape Inner class too.

Inference:
After the anonymous inner class holds the this reference of the outer class, it may call the instance method of the outer class (not a private method, nor a final method). At this time, it is of course called through this reference ( this.doSomething is not written in the code (e), which is a shorthand ). The object pointed to by this reference may cause problems by calling its instance method to change properties before it is fully constructed . For example, when the external class is initialized, an int type parameter is assigned, and then the doSomething(e) method adds 1 to the parameter. What if the onEvent() method fires before the outer class has finished initializing? would be embarrassing. Because this reference is obtained by the EventListener instance object in advance. This early acquisition is the escape of this reference .
So the book concludes that calling a rewritable instance method (not a private method or a final method) in a constructor will also cause the this reference to escape during the construction process. The same is true for threads that cannot be started in the constructor, that is, calling the method of the object privately when the initialization is not completed, changing its state, there will be hidden dangers.
And the book also said that the solution is to register an event listener or start a thread in the constructor, you can use a private constructor and a public factory method (Factory Method), so as to avoid incorrect construction process. As shown in the figure
insert image description here
, the registration listener is executed after construction, and the onEvent() method is guaranteed to be called after the construction of SafeListener. After the object is correctly initialized, calling the method of the object pointed to by this reference to modify the property is not escape, but release .

 

Guess you like

Origin blog.csdn.net/gaoshan12345678910/article/details/127784343