Это основан на этом вопросе. Рассмотрим этот пример, когда метод возвращает Consumer
на основе выражения лямбда:
public class TestClass {
public static void main(String[] args) {
MyClass m = new MyClass();
Consumer<String> fn = m.getConsumer();
System.out.println("Just to put a breakpoint");
}
}
class MyClass {
final String foo = "foo";
public Consumer<String> getConsumer() {
return bar -> System.out.println(bar + foo);
}
}
Как мы знаем, это не очень хорошая практика, чтобы ссылаться на текущее состояние внутри лямбда при выполнении функционального программирования, одна из причин заключается в том, что лямбда захватит охватывающий экземпляр, который не будет собираться мусором, пока сама лямбда не окажется вне сфера.
Однако в этом конкретном сценарии, связанном с строками final
, кажется, что компилятор мог просто вставить строку константы (final
) foo
(из пула констант) в возвращаемой лямбда, вместо того, чтобы вставлять весь MyClass
экземпляр, как показано ниже, при отладке (размещение прерывания на System.out.println
). Это связано с тем, как lambdas скомпилированы в специальный invokedynamic
байт-код?