A Java lambda referencing an element from its enclosing scope holds a reference to its enclosing object. A contrived example, with lambda holding ref to MyClass:
class MyClass {
final String foo = "foo";
public Consumer<String> getFn() {
return bar -> System.out.println(bar + foo);
}
}
This is problematic if the lifetime of the lambda is long; then we've got a ref to MyClass that is long-lived, when it would have otherwise gone out of scope. Here we can optimize by replacing the lambda with a private static class, so that we're only holding a reference to the String we need rather than to the entire class:
class MyClass {
private static class PrintConsumer implements Consumer<String> {
String foo;
PrintConsumer(String foo) {
this.foo = foo;
}
@Override
public void accept(String bar) {
System.out.println(bar + foo);
}
}
final String foo = "foo";
public Consumer<String> getFn() {
return new PrintConsumer(foo);
}
}
Unfortunately this is super verbose and destroys the nice syntax we get from using (effectively final) variables from enclosing scope in lambdas. Is this technically optimal? Is there always a tradeoff here between nice syntax and the possibility of keeping a ref longer than necessary?