Я некоторое время использовал лямбда-выражения и ссылки на методы в Java 8, и есть одна вещь, которую я не понимаю. Вот пример кода:
Set<Integer> first = Collections.singleton(1);
Set<Integer> second = Collections.singleton(2);
Set<Integer> third = Collections.singleton(3);
Stream.of(first, second, third)
.flatMap(Collection::stream)
.map(String::valueOf)
.forEach(System.out::println);
Stream.of(first, second, third)
.flatMap(Set::stream)
.map(String::valueOf)
.forEach(System.out::println);
Два потоковых конвейера делают одно и то же, они выводят три числа, по одному на строку. Разница в их второй строке, кажется, вы можете просто заменить имя класса в иерархии наследования, если у него есть метод (интерфейс Collection имеет метод по умолчанию «поток», который не переопределяется в интерфейсе Set). Я проверил, что происходит, если метод переопределяется снова и снова, используя эти классы:
private static class CustomHashSet<E> extends HashSet<E> {
@Override
public Stream<E> stream() {
System.out.println("Changed method!");
return StreamSupport.stream(spliterator(), false);
}
}
private static class CustomCustomHashSet<E> extends CustomHashSet<E> {
@Override
public Stream<E> stream() {
System.out.println("Changed method again!");
return StreamSupport.stream(spliterator(), false);
}
}
После изменения первого, второго и третьего назначений для использования этих классов я смог заменить ссылки на методы (CustomCustomHashSet::stream), и неудивительно, что они выводили отладочные сообщения во всех случаях, даже когда я использовал Collection::stream. Кажется, вы не можете вызвать супер, переопределенный метод со ссылками на методы.
Есть ли разница во времени выполнения? Что лучше: обратиться к интерфейсу/классу верхнего уровня или использовать конкретный известный тип (Set)? Спасибо!
Изменить: просто чтобы прояснить, я знаю о наследовании и LSP, мое замешательство связано с дизайном ссылок на методы в Java 8. Моя первая мысль заключалась в том, что изменение класса в ссылке на метод изменит поведение, которое он вызовет суперметод из выбранного класса, но как показали тесты, разницы нет. Изменение типов созданных экземпляров меняет поведение.