4

I think the easiest way to describe my question is with an example:

class Enclosing {
    private ObjectOfInterest o = new ObjectOfInterest();
    public void registerEventListener() {
        EventEmitter.onEvent(() -> {
            // Need to access 'o' here, while 'this' is not important.
            o.yeeha();
        });
    }
}

Does the lambda expression hold an implicit reference to its Enclosing instance? If so, how can I avoid this to avoid memory leaks? I need to access o in the event listener, but not the enclosing instance.

BTW, I found the question "Does Java8 lambdas maintains a reference to their enclosing instance like anonymous classes?", but it is not clear to me when exactly the lambda expression is considered to "not capture members from the enclosing instance". In addition, the document that is referenced in the accepted answer declares itself as outdated.

Community
  • 1
  • 1
x-ray
  • 3,279
  • 5
  • 24
  • 37
  • See the second answer to the question you reference (http://stackoverflow.com/a/28449928/5646962). According to that answer it is clear that your lambda expression **will** hold a reference to the enclosing class, since the lambda expression references the **member** o – Thomas Kläger Feb 16 '16 at 17:21

1 Answers1

5

Your lambda has to maintain a reference to Enclosing, because the value of the field may be changed between the lambda creation and execution. If you add next code to the end of registerEventListener:

o = null;

Then you will expect your event listener to fail with NullPointerException. Thus it has to hold a reference to this.

Also I should mention that it has to maintain reference to this even if the field is final, because its value can still be changed with the help of reflection.

However if you only need to use the value that was set at the moment of lambda creation, then you can create a local variable and use it in your lambda:

public void registerEventListener() {
    final ObjectOfInterest currentO = this.o;
    EventEmitter.onEvent(() -> {
        currentO.yeeha();
    });
}    
user3707125
  • 3,394
  • 14
  • 23
  • some arguments about capturing `final` fields -- see comments of http://stackoverflow.com/a/30362256/2158288 – ZhongYu Feb 16 '16 at 18:13
  • @bayou.io, can you please explain what did you mean? I wrote a [test](https://codetidy.com/7904), in which I change `final` field using reflection, and the lambda sees the change. – user3707125 Feb 16 '16 at 19:15
  • sure - but JVM does not need to honor reflective changes to `final` fields; it would be legit even if your test sees no change. Reflection is not the reason why lambda must capture `this` instead of a final field. – ZhongYu Feb 16 '16 at 19:28