Link to calling object-object via anonymous java class

I am reading Java concurrency in practice, and below are examples. And my questions. What do they mean by this link? What is the problem ?, How does this link come out of doSomething (e).

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

How does this solve the problem

 public class SafeListener { private final EventListener listener; private SafeListener() { listener = new EventListener() { public void onEvent(Event e) { doSomething(e); } }; } public static SafeListener newInstance(EventSource source) { SafeListener safe = new SafeListener(); source.registerListener(safe.listener); return safe; } } 

Edit:

I tried the examples below

 public class Escape { public Escape( Printer printer ){ printer.print(new Escaper(){ @Override public void parentData(){ theCulprit1(Escape.this); } public String name = "shal"; @Override public void theCulprit(){ System.out.println( this.name ); System.out.println( Escape.this.age ); } }); canAccess(); } public void canAccess(){ this.age = "25"; } public String age = "62"; @SuppressWarnings("unused") public static void main(String args[]){ Escape escape = new Escape(new Printer()); } } class Printer{ public void print(Escaper escaper){ escaper.theCulprit(); escaper.parentData(); } } class Escaper{ public void parentData(){ } public void theCulprit(){ } public void theCulprit1(Escape escape){ System.out.println(escape.age); } } 

Due to the incomplete design of the rescue facility, this displays shal 62 62

Where I changed my code like this

 public class Escape { private final Escaper escaper; private Escape( ){ escaper = new Escaper(){ @Override public void parentData(){ theCulprit1(Escape.this); } public String name = "shal"; public void theCulprit(){ System.out.println( name ); System.out.println( age ); } }; canAccess(); } public void canAccess(){ age = "25"; } public String age = "62"; public static Escape newInstance( Printer printer){ Escape escape = new Escape(); printer.print(escape.escaper); return escape; } @SuppressWarnings("unused") public static void main(String args[]){ Escape.newInstance(new Printer()); } } 

Here "- where exactly. He displays shal 25 25

I'm right? There is also a reordering of operations, since in the first example the age was initialized to 62. Even without making the final escaper field in the second example, it works!

+6
java reference this concurrency anonymous-class
source share
2 answers

In the first form, the event listener object is registered in the event source inside the constructor , and thus it makes (and by association the "this" object) accessible to the event source until the constructor completes. If the internal object of the class fails, then the external object.

Why is this a problem? Once an event listener is registered, the event source can reference its methods at any time. Imagine that a thread that uses an event source starts an event listener method call. This can happen even before the constructor completes.

This problem is worse than it seems due to visibility issues. Even if you make the registration the "last operation" that the constructor performs, there is still the opportunity to see the partially constructed object or the object in an invalid state. There is simply no guarantee of visibility in the absence of a proper incident - before ordering.

Declaring this final, this happens - before the order (thus, the second form).

+8
source share

when you have an inner class that is not static, like

 class Outer { class Inner { } } 

the inner class has a hidden field that refers to the outer class, so you can imagine what it looks like

 class Outer { class Inner { Outer hiddenOuter; } } 

Thus, wherever an internal object is used, the external object is a reference, and therefore its lifetime is not less than the internal object.

+2
source share

All Articles