Пытаюсь написать параметризуемый метод, принимающий параметризованные типы:
public static <T> void findMinMax(
Stream<? extends T> stream,
Comparator<? super T> comparator,
BiConsumer<? super T, ? super T> minMaxConsumer
) {
Stream<T> sortedStream = stream.sorted(comparator);
}
Объявление метода имею из условия задачи. Непонятны две вещи:
Не понимаю почему stream
может параметризоваться любым подтипом T
, а comparator
любым родительским типом T
. То есть почему у stream
тип Stream<? extends T>
, а у comparator
- Comparator<? super T>
? С какой целью это сделано?
В данный момент при компиляции вылетает ошибка:
error: incompatible types: Stream<CAP#1> cannot be converted to Stream<T>
Stream<T> sortedStream = stream.sorted(comparator);
^
where T is a type-variable:
T extends Object declared in method <T>findMinMax(Stream<? extends T>,Comparator<? super T>,BiConsumer<? super T,? super T>)
where CAP#1 is a fresh type-variable:
CAP#1 extends T from capture of ? extends T
Не могу понять, что не так. Ведь T
является и своим подтипом и своим супер-типом. Почему тогда компилятор говорит о несовместимости типов? Что компилятор подразумевает под CAP#1
?
Generics (Обобщенные типы) инвариантны, то есть нельзя присвоить к Stream<Number>
ссылку на Stream<Double>
. Wildcard (Маска) придает свойство вариантности при взаимодействии с обобщенными типами рассматривая их либо как источники объектов Т (Producer Extends, см. PECS), либо как приёмники Т (Consumer Super, см. PECS).
Wildcard это не Generic, это специальный тип параметризации, его можно использовать только при декларировании переменных или аргументов методов, все Wildcard содержат вопросительный знак - ?
.
Инвариантный Generic (Обобщенный тип):
List<T>
- List принимает T и его наследников, и возвращает объекты Т.
Ковариантность достигается через Upper Bounded Wildcards ? extends T
:
List<? extends T>
- List возвращает объекты Т, так как содержит объекты Т либо наследников Т:
List<? extends Number> numbers = new ArrayList<Double>() {{ add(2.5); }};
Number n = numbers.get(0);
Контравариантность достигается через Lower Bounded Wildcards ? super T
:
List<? super T>
- List принимает объекты T и его наследников:
List<? super Number> objects = new ArrayList<Object>() {{ add(2.5); add("it's fine!"); }}
objects.add((short) 256);
Этот wildcard указывает, что исходный List может содержать что угодно, вплоть до Object, по этой причине метод get(n)
вернет Object, но wildcard позволит передать в List объекты с типом Number и его наследников.
Разбор ошибки:
public static <T> void findMinMax(Stream<? extends T> stream) {
Stream<T> sortedStream = stream.sorted(comparator);
}
Ошибка из-за попытки присвоить Upper Bounded Wildcards к типу Stream.
Почему так сделать нельзя:
List<? extends Number> containsNumbers = new ArrayList<Double>();
containsNumbers.add(new Integer(100)); // Ошибка, wildcard `? extends Number` позволяет только прочитать объекты типа `Number`.
List<Number> numbers = containsNumbers // Ошибка, нельзя присвоить List<? extends Number>
numbers.add(new Integer(200)); // если бы не ошибка выше, то можно было бы добавить объект неподходящего типа
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Сразу скажу, что знаю, есть, Javaparser проект, но он от сторонних разработчиковЯ просто не могу понять если java компилируется в байт-код из исходников,...
Не могу понять, чем прокси класс который создается, когда я в BeanPostProcessor добавляю какую-нибудь логику после инит метода отличается от того...
Импортировал библиотеку, но приложение не компилируетсяКод исходный, я ничего не менял