Stream.anyMatch
определяется как:
boolean anyMatch(Predicate<? super T> predicate)
Я создал новый класс следующим образом:
class ClassA {
public boolean anyMethodName(Object o) {
return o instanceof Integer;
}
}
Тогда я могу запустить следующее:
List<String> durunitList = Arrays.asList("h", "d", "w", "m", "y");
ClassA classA = new ClassA();
System.out.println(durunitList.stream().peek(System.out::println).anyMatch(classA::anyMethodName));
Но в моем ClassA
я не реализовал Predicate
или его функциональный метод:
boolean test(T t)
Почему classA::anyMethodName
все еще можно передать Stream.anyMatch(...)
?
В Java 8 добавлена возможность интерфейсов быть «функциональными интерфейсами», если интерфейс имеет один абстрактный метод. Если да, то компилятор позволяет вам использовать метод (как лямбда-выражение или ссылку на метод classA::anyMethodName
), как если бы он был экземпляром этого интерфейса, создавая для вас анонимный класс (при условии, что он имеет тот же тип возвращаемого значения). /параметры).
Предикат — это функциональный интерфейс, который позволяет вам напрямую использовать метод classA::anyMethodName
, как если бы он был экземпляром Predicate
.
В конце концов, ваш код фактически преобразуется в:
List<String> durunitList = Arrays.asList("h", "d", "w", "m", "y");
ClassA classA = new ClassA();
System.out.println(durunitList.stream().peek(System.out::println).anyMatch(new Predicate<String>() {
@Override
public boolean test(String o) {
return classA.anyMethodName(o);
}
}));
ClassA
никогда не приводится к Predicate
(поскольку это не предикат...), но новый анонимный класс, который реализует Predicate
, просто вызывает classA.anyMethodName
за кулисами.
Но в моем определении ClassA НЕТ ключевого слова «реализует предикат», почему компилятор по-прежнему считает, что ClassA является реализацией предиката интерфейса?
ClassA
никогда не рассматривается как Predicate
и не приравнивается к нему. Обратите внимание, как в финальном коде (примера) создается новый анонимный класс, который реализует Predicate
(следовательно, @Override public boolean test
), который затем вызывает ваш метод classA.anyMethodName
.
ваше второе предложение вводит в заблуждение, @FunctionalInterface
АННОТАЦИЯ для этого не требуется - аннотация, как указано в предоставленной вами ссылке, является «информационной аннотацией» (аналогично @Override
, не требуется, но проверяется, если присутствует) - Спецификация языка Java 9.8. Функциональные интерфейсы : «Функциональный интерфейс — это интерфейс, который не объявлен запечатанным и имеет только один абстрактный метод (кроме методов Object) и, таким образом, представляет собой единый функциональный контракт».
@ user85421, спасибо, я перепишу эту часть! (также я называл их атрибутами, потому что у меня в голове был C#, лол)
Как вы пришли к выражению
classA::anyMethodName
, единственная цель которого — сделать возможным то, чему вы сейчас удивляетесь? Почему вас удивляет возможность использования ссылки на метод там, где ожидается предикат, при этом замалчивая тот факт, что вы также используетеSystem.out::println
там, где ожидаетсяConsumer
?