Есть ли делегаты в Java 8?
Есть ли делегаты в Java 8?
Если нет, то как мы имеем лямбда-выражения в JDK 8 Без делегатов?
Что такое ссылки на методы ? Они такие же, как делегаты?
2 ответов:
В JDK 8 нет делегатов. Под капотом лямбды находятся экземпляры функциональных интерфейсов (интерфейс с ровно одним абстрактным методом). В зависимости от того, где вы передаете свой лямбда-код, компилятор может определить, какой интерфейс он реализует. Например, коллекции.метод сортировки принимает экземпляр компаратора в качестве второго параметра. Компаратор является функциональным интерфейсом, поэтому компилятор проверяет, соответствует ли передаваемый лямбда-код абстрактному методу. Компаратор или нет.
Ссылка на метод-это просто упрощение. Когда ваш лямбда-код просто вызывает существующий метод, вы можете использовать этот новый синтаксис для упрощения конструкции. Пример из связанного учебника показывает это довольно хорошо:Вместо:
Arrays.sort(rosterAsArray, (a, b) -> Person.compareByAge(a, b) );Проще со ссылкой на метод:
Arrays.sort(rosterAsArray, Person::compareByAge);Взгляните на lambdafaq.
Благодаря комментарию Пейсерье на этот вопрос, вот способ выполнить то, что делает делегат C# (one-function), даже вJava 7 или ниже.
// This defines the 'delegate'. public interface IA { int f(int a); } public class MyClass { // f1 and f2 have the same signature as 'IA.f'. private int f1(int a) { return a + 1; } private int f2(int a) { return 2 * a; } // These wrappers are one way to return a 'delegate'. // Each wrapper creates one instance of an anonymous class. // Notice that we did not have to declare MyClass as implementing IA, // and that we can wrap different methods of MyClass into 'IA's. // Contrast this with 'MyClass implements IA', which would require // a method 'f' in 'MyClass', and would not provide a way to // delegate to different methods of 'MyClass'. public IA wrapF1() { return (new IA(){ public int f(int a) { return f1(a); } }); } public IA wrapF2() { return (new IA(){ public int f(int a) { return f2(a); } }); } // returns a 'delegate', either to 'f1' or 'f2'. public IA callMe(boolean useF2) { if (!useF2) return wrapF1(); else return wrapF2(); } }Использование
... // Create and use three 'delegates'. // Technically, these are not quite the same as C# delegates, // because we have to invoke a method on each. // That is, we must do 'ia0.f(..)' instead of 'ia0(..)'. // Nevertheless, it satisfies the design requirement. MyClass c = new MyClass(); IA ia0 = c.wrapF1(); IA ia1 = c.callMe(false); IA ia2 = c.callMe(true); int result0 = ia0.f(13); int result1 = ia1.f(13); int result2 = ia2.f(13);Урожайность
result0: 14 <-- f1, so 13 + 1 result1: 14 <-- f1, so 13 + 1 result2: 26 <-- f2, so 2 * 13
Примечание: Если вам нужна только одна реализация для каждого класса данного "делегата", то более простым решением является непосредственная реализация интерфейса в классе. Вот вам пример. Класс уже имел
f3, и теперь он расширен для реализацииIA:public class MyClass2 implements IA { private int baseValue; private int anotherValue; public MyClass2(int baseValue, int anotherValue) { this.baseValue = baseValue; this.anotherValue = anotherValue; } public int f3(int v1, int v2) { return 2 * v1 + v2; } public int f(int a) { return f3(baseValue + a, anotherValue); } } IA ia3 = new MyClass2(10, 3); int result3 = ia3.f(13); // = f3(10 + 13) = 2 * 23 + 3 = 49В этом случае он ничем не отличается от любой другой реализации интерфейса. Дело в том, что
design conceptвозвращаемая функция, соответствующая указанной сигнатуре , может быть удовлетворена с помощью дополнительного кодирования с использованием интерфейсов Java. Во втором, более простом, случае интерфейс помещается непосредственно на класс. В первом, более общем случае, интерфейс помещается на анонимный экземпляр анонимного внутреннего класса. Для ясности и легкого доступа я изолирую их 'создатели делегата в функцию-оболочку.Верно, что результат не совсем совпадает с делегатом C#, потому что нужно делать
ia.f(), а неia(). Тем не менее, цель проекта была достигнута.
Примечание: ВJava 8 кодирование упрощается с помощью лямбд. Я не использую Java 8, поэтому я не буду включать здесь реализацию Java 8. (Любой желающий может отправить правку, которая добавляет эту реализацию. Я предлагаю показать новые тела ниже для моего
wrapF1()иwrapF2()выше, так как это облегчило бы сравнение версий Java 7 и Java 8.)
Comments