SayHello
- это интерфейс с одним абстрактным методом, который имеет метод, который принимает строку и возвращает void. Это аналогично потребителю. Вы просто предоставляете реализацию этого метода в форме потребителя, которая похожа на следующую анонимную реализацию внутреннего класса.
SayHello sh = new SayHello() {
@Override
public void speak(String message) {
System.out.println("Hello " + message);
}
};
names.forEach(n -> sh.speak(n));
К счастью, ваш интерфейс имеет единственный метод, такой что система типов (более формально)алгоритм определения типа) может выводить его тип как SayHello
. Но если бы у него было 2 или более методов, это было бы невозможно.
Однако гораздо лучший подход - объявить получателя перед циклом for и использовать его, как показано ниже. Объявление реализации для каждой итерации создает больше объектов, чем необходимо, и кажется мне нелогичным. Вот расширенная версия, использующая ссылки на методы вместо лямбды. Использованная здесь ссылка на ограниченный метод вызывает соответствующий метод в объявленном выше экземпляре hello
.
SayHello hello = message -> System.out.println("Hello " + message);
names.forEach(hello::speak);
Обновление
Учитывая, что для лямбд без сохранения состояния это не захватываетчто-либо из их лексического контекста только один раз когда-либо будет создано, оба подхода просто создают один экземпляр SayHello
, и после предложенного подхода нет никакой выгоды. Однако это, кажется, деталь реализации, и я не знал об этом до сих пор. Так что гораздо лучший подход - просто передать потребителю свой forEach, как это предлагается в комментарии ниже. Также обратите внимание, что все эти подходы создают только один экземпляр вашего SayHello
интерфейса, в то время как последний более лаконичен. Вот как это выглядит.
names.forEach(message -> System.out.println("Hello " + message));
Этот ответ даст вам более полное представление об этом. Вот соответствующий раздел из JLS §15.27.4 : Оценка лямбда-выражений во время выполнения
Эти правила предназначены для обеспечения гибкости для реализаций языка программирования Java, вчто:
- При каждой оценке не требуется выделять новый объект.
На самом деле, я изначально думал, что каждая оценка создает новый экземпляр, что неправильно,@ Хольгер, спасибо за указание, хороший улов.