Java lambda, ссылающаяся на элемент из своей охватывающей области, содержит ссылку на свой охватывающий объект. Надуманный пример: lambda hold to myClass:
class MyClass {
final String foo = "foo";
public Consumer<String> getFn() {
return bar -> System.out.println(bar + foo);
}
}
Это проблематично, если время жизни лямбда длинное; то у нас есть ссылка на MyClass, которая долговечна, когда она иначе выйдет за рамки. Здесь мы можем оптимизировать, заменив лямбда частным статическим классом, так что мы используем только ссылку на нужную нам строку, а не на весь класс:
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);
}
}
К сожалению, это супервероятно и уничтожает хороший синтаксис, который мы получаем от использования (эффективно конечных) переменных из охватывающей области в lambdas. Это технически оптимально? Всегда существует компромисс между хорошим синтаксисом и возможностью сохранения ref дольше, чем необходимо?