Правила лямбда-кастинга


Мне было любопытно, почему лямбда с возвращаемым типом не может быть приведена к Runnable, тогда как ссылка на метод non void может.

Runnable r1 = () -> 1; // not allowed
// error: incompatible types: bad return type in lambda expression
// int cannot be converted to void

Runnable r2 = ((Supplier)() -> 1)::get; // allowed
2 12

2 ответа:

Runnable интерфейс определяет метод run с возвращаемым типом void. В лямбда-выражении это означает, что часть, следующая за стрелкой ->, должна быть оператором . Это объясняется в JLS §15.27.3:

Если результатом типа функции является void, то лямбда-тело является либо выражением оператора (§14.8), либо блоком, совместимым с void.

JLS $14.5 четко определяет синтаксис оператора. Как было объяснено выше, это должно быть an "ExpressionStatement" (§ 14.8). Глядя туда, вы можете обнаружить, что простой литерал не является адекватным выражением, но вызов метода является (даже если он возвращает что-то).

На самом деле это не" специальное " правило для лямбд. Всегда было приемлемо использовать метод non-void в контексте оператора (в этом случае возвращаемое значение отбрасывается), но не так с простым выражением. Например, " строка.valueOf (true);" является допустимым утверждением java, которое может занимать строку само по себе, тогда как "true;" не является и не может быть.