Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

'this' reference escape in case of lambda in constructor

With reference to this question -

How does `this` reference to an outer class escape through publishing inner class instance?

If we replace the anonymous class with the lambda or the method reference why and how this code is going to behave?

public class ThisEscape {
    public ThisEscape(EventSource source) {
         source.registerListener(e -> doSomething(e));
    }
}
like image 686
Mandeep Rajpal Avatar asked Mar 16 '26 00:03

Mandeep Rajpal


2 Answers

Technically there is not much of a difference between creating an anonymous inner class or using a lambda. Lambdas are more of less just syntax candy to make something Java was capable of doing all the time more prominent, accessible and less error prone. That is your code is subject to the same race condition described in the question you referred to and its answer.

With the given code construct you got no guarantee that the instance of ThisEscape is properly created before doSomething is called.

Read the javaspecialists.eu newsletter that is linked in this answer to understand under what circumstances that might be problematic.

like image 156
dpr Avatar answered Mar 17 '26 14:03

dpr


In the original question the code

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

is problematic because the object have been registered in the constructor and then may be used by the event managing system while not being fully constructed. In fact, this is dangerous only if doSomething access something external to the ThisEscape instance.

And this is the same with your lambda "equivalent"

public class ThisEscape {
    public ThisEscape(EventSource source) {
         source.registerListener(e -> doSomething(e));
    }
}

But don't be fooled, anonymous inner classes are not strictly equivalent to lambdas... this refers to the current instance in case of anonymous inner class but refers to the enclosing instance of the lambda (this is in the closure of the lambda) :

interface doable {
    public void doIt();
}
public class Outer {
    public Outer() {
        doable d1 = new doable() {
            public void doIt() {
                System.out.println(this);
            }
        };
        d1.doIt();

        doable d2 = ()->System.out.println(this);
        d2.doIt();
    }
    public static void main(String []argv) {
        new Outer();
    }
}

produces something like :

Outer$1@3764951d
Outer@3cd1a2f1

The second line clearly shows that a lambda is not an instance of any class, it is not an object.

like image 45
Jean-Baptiste Yunès Avatar answered Mar 17 '26 14:03

Jean-Baptiste Yunès



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!