Пытаюсь написать параметризуемый метод, принимающий параметризованные типы:
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)); // если бы не ошибка выше, то можно было бы добавить объект неподходящего типа
Сразу скажу, что знаю, есть, Javaparser проект, но он от сторонних разработчиковЯ просто не могу понять если java компилируется в байт-код из исходников,...
Не могу понять, чем прокси класс который создается, когда я в BeanPostProcessor добавляю какую-нибудь логику после инит метода отличается от того...
Импортировал библиотеку, но приложение не компилируетсяКод исходный, я ничего не менял