81 подписчик
Wildcards в Java Generics
Продолжаем изучать тему дженериков.
Wildcards.
Это очень важная фишка дженериков.
Пример:
public class Main {
public static void main(String[] args) {
String str = new String("Test!");
// никаких проблем
Object obj = str;
List<String> strings = new ArrayList<String>();
// ошибка компиляции!
List<Object> objects = strings;
}
}
Что же тут происходит?
Мы видим две очень похожие ситуации. В первой из них мы пытаемся привести объект String к типу Object. Никаких проблем с этим не возникает, все работает как надо.
Но вот во второй ситуации компилятор выдает ошибку. Хотя, казалось бы, мы делаем то же самое. Просто теперь мы используем коллекцию из нескольких объектов.
Но почему возникает ошибка? Какая, по сути, разница — приводим мы один объект String к типу Object или 20 объектов?
Между объектом и коллекцией объектов есть важное различие.
Если класс B является наследником класса А, то Collection<B> при этом — не наследник Collection<A>.
Именно по этой причине мы не смогли привести наш List<String> к List<Object>. String является наследником Object, но List<String> не является наследником List<Object>.
Интуитивно это выглядит не очень логично. Почему именно таким принципом руководствовались создатели языка?
Давай представим, что здесь компилятор не выдавал бы нам ошибку:
List<String> strings = new ArrayList<String>();
List<Object> objects = strings;
В этом случае, мы бы могли, например, сделать следующее:
objects.add(new Object());
String s = strings.get(0);
Поскольку компилятор не выдал нам ошибок и позволил создать ссылку List<Object> object на коллекцию строк strings, можем добавить в strings не строку, а просто любой объект Object!
1 минута
19 июня 2023