Ответ 1
Ошибка JDK-8027941 описывает именно это. Дэн Смит (Project Lambda Specification Lead) пишет, что это не ошибка, и не ограничивается лямбдами.
В комментариях к связанному отчету об ошибках он делает следующее:
8.3.2.3: Во-первых, "использование" поля в инициализаторе поля обычно запрещено, если использование происходит до объявления поля. Спецификация не очень понятна в этом, но всегда было намерением, что "до" включает собственный инициализатор поля. Поэтому "
int x = x+1;
" не является допустимым объявлением поля.
Он также замечает:
Можно было бы добавить функцию, которая специально обрабатывала бы лямбда-тела, например тела анонимных классов (или, в более общем плане, разрешать лямбда ссылаться на себя, если она является переменным инициализатором), но это еще не сделано. (FWIW, простая настройка 8.3.2.3 не была бы полностью безопасной, так же как четвертая пуля в настоящее время не полностью безопасна: "
Function f = (Function) ((Function) e -> f.apply(e)).apply(null);
".)
Я думаю, проблема заключается в том, что разработчики Java хотят иметь простые синтаксические правила, чтобы решить, какие утверждения разрешены, а не в зависимости от более сложного анализа семантического кода. Преимущество, вероятно, более простая спецификация и, следовательно, меньшее количество требований к компиляторам, в то время как стоимость заключается в том, что программисты не могут выразить каждую программу - по крайней мере, не так, как они хотят.
Как отмечает Марко Топольник, есть решение: полностью квалифицировать поле. Пример из отчета об ошибке:
import java.util.function.Function;
public class LambdaSelfRef {
// COMPILATION FAILURE
public static Function<Object, Object> op1 = e -> op1.apply(e);
// COMPILES OK
public static Function<Object, Object> op2 = e -> LambdaSelfRef.op2.apply(e);
/* ... */
}