Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference of enclosing object escape through anonymous class- java

I am reading Java concurrency in practice and the below examples are from that. And my questions are What do they mean by this reference escape?. What will be the problem? . How does the this reference escapes from doSomething(e).

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

How does this solves 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 have tried the below examples

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 incomplete construction of the escape object This outputs shal 62 62

Where as 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());
    }
}

Where as here.It outputs shal 25 25

Am i right ? Also is there any re-ordering of operations, because in the first example the age got initialized to 62. Even without making the escaper field final in my second example it works !

like image 899
John Avatar asked Feb 26 '11 20:02

John


People also ask

How do you reference an outer class in Java?

In general you use OuterClassName. this to refer to the enclosing instance of the outer class.

How do you call an anonymous class in Java?

Object = new Example() { public void display() { System. out. println("Anonymous class overrides the method display()."); } }; Here, an object of the anonymous class is created dynamically when we need to override the display() method.

What is the use of anonymous object in Java?

Anonymous object in Java means creating an object without any reference variable. Generally, when creating an object in Java, you need to assign a name to the object. But the anonymous object in Java allows you to create an object without any name assigned to that object.

What is anonymous class and object in Java?

Anonymous classes enable you to make your code more concise. They enable you to declare and instantiate a class at the same time. They are like local classes except that they do not have a name. Use them if you need to use a local class only once.


1 Answers

In the first form, the event listener object gets registered to the event source within the constructor, and thus it makes itself (and by association the "this" object) available to the event source before the constructor completes. If the inner class object escapes, so does the outer object.

Why is this a problem? Once the event listener is registered, the event source may invoke its methods at any time. Imagine a thread that the event source is using starts invoking the event listener methods. This now can happen even before the constructor completes.

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

Declaring it final affords that happens-before ordering (thus the second form).

like image 113
sjlee Avatar answered Oct 20 '22 11:10

sjlee