ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: извините, но я не смог понять ваш вопрос, но я все же думаю, что мог бы поддержать добавление моих жестких навыков. Надеюсь, не так уж много "провалов" :)
Все дело в перспективе. Если мне нужно объяснить, что такое лямбда и как ее использовать, я буду использовать следующую абстракцию:
- Функциональный интерфейс:
- Один абстрактный метод подпись (застряла с publi c, поскольку это член интерфейса -> обобщенные типы, тип возвращаемого значения, типы аргументов, предложение throws ->
public <T> void processT(T t)
, public <T,R> R evalT(T t)
et c.) - Может иметь ноль или больше не абстрактных методов (по умолчанию / stati c).
- Абстрактный метод не имеет доступа к другим членам экземпляра в любой точке!
Lambdas:
- Чистые реализации метода (или, как я их называю, реализации анонимных методов для известных функциональных интерфейсов). Чтобы компилятор мог распознать лямбда-оператор как действительный, он должен встретить особенность метода из любого известного функционального интерфейса во время компиляции (целевая лента не может быть аннотирована с помощью @FunctionalInterface вместо того, чтобы иметь один абстрактный метод и быть самим интерфейсом ( ref для абстрактных классов ).
Теперь давайте внимательнее рассмотрим ваш конкретный пример:
Consumer -> метод void, который принимает один аргумент (generi c, указанный тип) и выполняет некоторую обработку на основе ввода.
Давайте теперь рассмотрим ваш код и небольшие витрины, которые я добавил туда для вас.
import java.util.function.Consumer;
public class ConsumerTest {
@Data
public static class Person{
private Integer id;
private String name;
private String surName;
}
@Data
public static class Student{
private Integer id;
private Person person;
}
public static void main(String args[])
{
Student student = new Student();
student.setId(1);
Person person = new Person();
person.setName("Ali");
person.setSurName("Veli");
person.setId(2);
student.setPerson(person);
/* shorthand definition for anonymous implementation in place, recognisable signature */
Consumer<Student> displayLambda = s -> s.getPerson().setSurName("Gülsoy");
/* full definition for anonymous implementation in place, allows annotations */
Consumer<Student> anotherDisplayLambda = new Consumer<Student>() {
@Override
public void accept(Student student) {
student.getPerson().setSurName("Gülsoy");
}
};
// And finally:
/* acquires reference to anonymous implementation with recognisable signature */
Consumer<Student> yetAnotherDisplayLambda = ConsumerTest::thisIsAMethodButAlsoAConsumer;
/* invokes the implementations, a.k.a. method call, method invocation */
displayLambda.accept(student);
anotherDisplayLambda.accept(student);
yetAnotherDisplayLambda.accept(student);
/* also valid statements, but this time it captures instance member, so make sure how it works under the hood */
displayLambda = anotherDisplayLambda::accept; // same as `displayLambda = anotherDisplayLambda`
}
// if you can "retrieve that function" here than you should be able to answer your question as well...
private static void thisIsAMethodButAlsoAConsumer(Student student) {
student.getPerson().setSurName("Gülsoy");
}
}
Теперь, давайте продолжим копать:
import java.util.function.Consumer;
public class ConsumerTest {
@Data
public static class Person{
private Integer id;
private String name;
private String surName;
}
@Data
public static class Student{
private Integer id;
private Person person;
}
private interface AnotherTypeOfInterface /* extends Consumer<Student> */
{
// if you can "retrieve that function" here than you should be able to answer your question as well...
void consumeStudentObject(Student student);
}
public static void main(String args[])
{
Student student = new Student();
student.setId(1);
Person person = new Person();
person.setName("Ali");
person.setSurName("Veli");
person.setId(2);
student.setPerson(person);
/* Target interface is not annotated as functional, still we got things done :)
* If you comment out the extend clause in AnotherTypeOfInterface then @FunctionalInterface annotation will be required */
AnotherTypeOfInterface anotherTypeOfConsumer = ConsumerTest::thisIsAMethodButAlsoAConsumer;
/* throwsException in thread "main" java.lang.ClassCastException: ConsumerTest$$Lambda$3/2093631819 cannot be cast to
* java.util.function.Consumer, unless you comment out the extend clause in interface definition */
// Consumer<Student> interfacesAreStillTypes = anotherTypeOfConsumer;
/* but this one doesn't throw as it parses all it needs -> anonymous method signature and definition... */
Consumer<Student> yetAnotherTypeOfConsumer = anotherTypeOfConsumer::consumeStudentObject
/* invokes the implementation */
anotherTypeOfConsumer.consumeStudentObject(student);
// interfacesAreStillTypes.accept(student);
yetAnotherTypeOfConsumer.accept(student);
}
}
В последнем примере AnotherTypeOfInterface будет иметь единственный метод с именем consumeStudentObject
, который будет соответствовать Consumer::accept
, однако экземпляры Consumer имеют свой собственный набор членов, например Consumer::andThen
.