Может ли Java 8 реализовать интерфейс "на лету" для ссылки на метод?
Я изучаю новые возможности Java 8.
Я играю с разными примерами, и я нашел странное поведение:
public static void main(String[] args) {
method(Test::new);
}
static class Test{
}
private static void method(Supplier<Test> testSupplier){
Test test = testSupplier.get();
}
Этот код успешно компилируется, но я не знаю, как это работает.
Почему Test::new
приемлемо как поставщик?
Интерфейс поставщика выглядит очень просто:
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Ответы
Ответ 1
Интерфейс Supplier
имеет единственный (функциональный) метод, который:
- не принимает никаких параметров;
- возвращает объект.
Поэтому любой метод, соответствующий этим двум точкам, соответствует функциональному контракту Supplier
(потому что методы будут иметь одну и ту же подпись).
Здесь рассматриваемый метод является ссылкой на метод. Он не принимает никаких параметров и возвращает новый экземпляр Test
. Вы можете переписать его на:
method(() -> new Test());
Test::new
в синтаксическом сахаре для этого лямбда-выражения.
Ответ 2
Test::new
- это ссылка на метод. Вместо того, чтобы добавлять новое объяснение, стоит взглянуть на учебник для ссылок на методы, поскольку он объясняет их довольно хорошо.
Прямой ответ на ваш вопрос заключается в том, что Supplier
- это функциональный интерфейс, что означает, что он имеет один метод, отличный от метода по умолчанию. Конструктор для Test
имеет ровно одну и ту же подпись (без аргументов, возвращает Test
), и поэтому можно напрямую ссылаться на создание анонимного Supplier
.
Есть четыре варианта ссылок на методы: ознакомьтесь с учебником, чтобы понять их все.
Ответ 3
Это может быть Function
, а не поставщик, если требуется аргумент. Но ссылки на методы могут ссылаться на конструкторы таким же образом, как они относятся к методам; у них просто смешное имя (new
).
Из учебника по Java, существует четыре типа ссылок на методы:
Kind Example
------------------------------- ------------------------------------
Reference to a static method ContainingClass::staticMethodName
Reference to an instance method containingObject::instanceMethodName
of a particular object
Reference to an instance method ContainingType::methodName
of an arbitrary object of a
particular type
Reference to a constructor ClassName::new