Пожалуйста, посмотрите этот код:
public interface Worker {
void work(double a);
}
public class Employee {
public static void test() {
System.out.println("Test");
}
public static void test(double a) {
System.out.println("Number : " + a);
}
}
public class MainClass {
public static void main(String[] args) {
Worker w = Employee::test;
w.work(12);
}
}
Как можно создать новый объект Employee
в качестве интерфейса Worker без его реализации?
Вы имеете в виду, что это лямбда-функция?
@Turing85: Turing85: Здесь нет лямбда-выражений - только ссылка на метод. (Вы можете использовать лямбду для реализации функционального интерфейса, но этот код этого не делает.)
Ваш вопрос не имеет никакого смысла. Пожалуйста, объясните немного больше, чего вы на самом деле хотите. Вы можете реализовать интерфейс Worker
без реализации какого-либо класса: Worker w = a -> a * 2;
или даже Worker w = a -> {System.out.println("Worker working..."); return a * 2;};
. Но зачем вам тогда Employee
в вашем коде или позволить Employee
реализовать Worker
? Мне кажется, вы там что-то путаете. Пожалуйста, исправьте свой вопрос.
@JayC667 JayC667, я читаю тот же код только в сообществе linkedin, меня это только смущает!
@Turing85: Меня это сбивает с толку, учитывая, что фактическая спецификация определяет лямбда-выражения совершенно отдельно. Действительно, спецификация ссылок на методы включает (при обсуждении перегрузки): «Это должно удовлетворять подавляющему большинству случаев использования; когда возникает редкая необходимость в более точном управлении, можно использовать лямбда-выражение», что предполагает, что спецификация соответствует не рассматривать ссылки на методы как лямбда-выражения. Я бы предположил, что здесь спецификация более точна, а руководство просто запутано.
@Turing85: Аналогичным образом, в разделе спецификации для лямбда-выражений есть: «Практически говоря, лямбда-выражению необычно говорить о себе (либо рекурсивно вызывать себя, либо вызывать другие методы), хотя чаще встречается хотите использовать имена для ссылки на элементы включающего класса, которые в противном случае были бы затенены (this, toString()). Если необходимо, чтобы лямбда-выражение ссылалось на себя (как если бы через this), ссылку на метод или анонимный объект. Вместо этого следует использовать внутренний класс». Опять же, это подсказывает мне различие между лямбда-выражениями и ссылками на методы.
@JonSkeet, как бы вы ни разрезали пирог, ссылки на методы тесно связаны с функциональными интерфейсами и лямбда-выражениями. IIRC, есть также детали реализации, то есть то, что компилятор и среда выполнения делают с соответствующим выражением.
@Turing85: Они определенно связаны с функциональными интерфейсами. Я просто не вижу смысла мутить воду между лямбда-выражениями и ссылками на методы, хотя мне они кажутся совершенно разными способами достижения схожих целей. (С точки зрения C#, любой, кто ссылается на преобразование группы методов как на лямбда-выражение, наверняка будет совершенно неправ.) Грамматика LambdaExpression также полностью отличается от грамматики ссылок на методы. Зачем объединять эти два понятия?
@JonSkeet То, что синтаксис другой, очевидно; как еще мы могли бы получить удобный способ написать «лямбду для уже существующего метода»? Сказать, что «у них разный синтаксис, следовательно, и разная семантика» — это w.l.o.g. неправильный. Лямбда-выражения и ссылки на методы используют одни и те же инструкции байт-кода. Поэтому я думаю, что объединение лямбда-выражений со ссылками на методы полезно, поскольку это один и тот же механизм. Я не уверен, какое значение имеет C#, поскольку пост посвящен Java.
@JonSkeet Если вам интересно, я могу предоставить пример, показывающий разницу в байт-коде между лямбда-выражением и ссылкой на метод.
Экземпляров Employee
не создано вообще. Вы используете ссылку на метод для реализации интерфейса Worker
, который является функциональным интерфейсом из-за наличия только одного абстрактного метода.
Ссылка на метод Employee::test
(перегрузка, принимающая параметр double
) удовлетворяет этому функциональному интерфейсу, поэтому преобразование ссылки на метод в функциональный интерфейс завершается успешно.
Интерфейс имеет только один метод, поэтому он является функциональным интерфейсом и может быть реализован с помощью лямбды. Лямбда — это «объект», который вы ищете.