JLS указывает, что
Если результат типа функции void, лямбда-тело является либо выражением инструкции (§14.8), либо блоком, совместимым с void.
Теперь давайте посмотрим на это подробнее,
Поскольку ваш takeBiConsumer
метод имеет тип void, получение лямбда new String("hi")
интерпретирует его как блок вроде
{
new String("hi");
}
который действителен в пустоте, следовательно, первый случай компиляции.
Однако в случае, когда лямбда есть -> "hi"
, такой блок, как
{
"hi";
}
недопустимый синтаксис в java. Поэтому единственное, что можно сделать со словом "привет" - это попытаться вернуть его.
{
return "hi";
}
который недействителен в пустоте и объяснит сообщение об ошибке
incompatible types: bad return type in lambda expression
java.lang.String cannot be converted to void
Для лучшего понимания обратите внимание, что если вы измените тип takeBiConsumer
на String, -> "hi"
он будет действителен, поскольку он просто попытается напрямую вернуть строку.
Обратите внимание, что сначала я подумал, что ошибка была вызвана тем, что лямбда находится в неправильном контексте вызова, поэтому я поделюсь этой возможностью с сообществом:
JLS 15.27
Это ошибка времени компиляции, если лямбда-выражение встречается в программе где-нибудь, кроме контекста присваивания (§5.2), контекста вызова (§5.3) или контекста приведения (§5.5).
Однако в нашем случае мы находимся в контексте вызова, что правильно.