Java
Что значит в данной строке "?" (какую функцию выполняет, зачем он там), за ранее спасибо!
public GeometryCollection(List<? extends T> elements) { this.elements = Collections.unmodifiableList(elements); }
Полиморфизм в дженериках - одно из тонких мест в Джаве.
Смысл в том, что если у нас есть иерархия классов
class Animal
class Cat extends Animal
class Dog extends Animal
то их массивы будут ковариантными этим типам, т. е. сохраняющими эту иерархию. Если у нас есть метод, принимающий Animal[] animals, то он также примет Cat[] cats и Dog[] dogs.
Дженерик-коллекции вариантность не сохраняют. Если метод принимает List< Animal>, то компилятор не даст передать ему List< Cat>. Главная причина - если параметр объявлен как List< Animal>, то в такой список можно потенциально добавить Dog, и рантайм никак не сможет узнать, что вообще-то изначально по факту был передан List< Cat> (в случае массивов здесь была бы ошибка во время выполнения). Все проблемы от того, что generic-типы существуют только в момент компиляции (см. понятие размытия типов (type erasure)).
Поэтому существуют маски и PECS-принцип (Producer extends, Consumer super), суть которого заключается в том, что
1. если в коллекцию добавляются/изменяются элементы, пишем List<? super Animal>,
2. если из коллекции читаются элементы, пишем List<? extends Animal> (не зря в твоем примере этот список делается unmodifiable).
Вот тут есть хорошая иллюстрация:
https://stackoverflow.com/questions/2723397/java-generics-what-is-pecs
Смысл в том, что если у нас есть иерархия классов
class Animal
class Cat extends Animal
class Dog extends Animal
то их массивы будут ковариантными этим типам, т. е. сохраняющими эту иерархию. Если у нас есть метод, принимающий Animal[] animals, то он также примет Cat[] cats и Dog[] dogs.
Дженерик-коллекции вариантность не сохраняют. Если метод принимает List< Animal>, то компилятор не даст передать ему List< Cat>. Главная причина - если параметр объявлен как List< Animal>, то в такой список можно потенциально добавить Dog, и рантайм никак не сможет узнать, что вообще-то изначально по факту был передан List< Cat> (в случае массивов здесь была бы ошибка во время выполнения). Все проблемы от того, что generic-типы существуют только в момент компиляции (см. понятие размытия типов (type erasure)).
Поэтому существуют маски и PECS-принцип (Producer extends, Consumer super), суть которого заключается в том, что
1. если в коллекцию добавляются/изменяются элементы, пишем List<? super Animal>,
2. если из коллекции читаются элементы, пишем List<? extends Animal> (не зря в твоем примере этот список делается unmodifiable).
Вот тут есть хорошая иллюстрация:
https://stackoverflow.com/questions/2723397/java-generics-what-is-pecs
Анатолий Ярош
спасибо
это называется типизированная маска - ?-тут - это то что мы получим в итоге.
тоесть List<? super Integer> - в итоге свернется в List< Integer > а например List<? extends Number> в некую абстракцию List < Integer + Long + Double + Short + .>
тоесть List<? super Integer> - в итоге свернется в List< Integer > а например List<? extends Number> в некую абстракцию List < Integer + Long + Double + Short + .>
Похожие вопросы
- Как сделать так,что бы минимальный элемент каждой строки оказался в начале? Что неправильно сделала
- Работа со строками Java Разработать программу, которая вводит строку и находит все слова указанной длины n (n вводится).
- Как работает рекурсивная функция?
- Изменение строки файла формата class
- Где можно найти краткое обучение по использованию JFrame? Чтобы просто приводился порядок поставления и функций.
- Java.Комментирование. Надо прокомеентировать каждую строку этой программы.
- Зачем нужны лямбда функции? И в частности в Котлине
- Как к последнему символу строки добавить единицу?
- Как реализовать замену строки текстового файла по индексу в java
- Этот вопрос давно меня мучает. Почему в более мощных языках программирования нужно самому объявлять тип данной переменой