Что такое ковариантность типов?
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
Ковариантность типов в Java означает, что при наличии иерархии типов Дочерний extends Родитель, можно использовать тип массива или генерика Дочерний[] там, где требуется Родитель[], или ArrayList<Дочерний> там, где требуется ArrayList<? extends Родитель>.
Примеры:
-
Массивы:
// Родительский класс class Animal {} // Дочерний класс class Dog extends Animal {} // Массив дочерних типов можно присвоить переменной массива родительских типов Animal[] animals = new Dog[10];Однако, попытка поместить в
animalsобъект другого типа, напримерCat, приведет кArrayStoreExceptionво время выполнения. Это ослабляет типовую безопасность массивов. -
Генерики: По умолчанию генерики инвариантны.
List<Dog>НЕ является подтипомList<Animal>. Для достижения ковариантности с генериками используются подстановочные типы (wildcards) с ключевым словомextends.// Метод принимает список, содержащий объекты Animal или его подтипов void processAnimals(List<? extends Animal> animals) { // Можно читать элементы (они гарантированно являются Animal или его подтипом) Animal first = animals.get(0); // НЕЛЬЗЯ добавлять элементы (неизвестно, какой именно подтип ожидается) // animals.add(new Dog()); // Ошибка компиляции // animals.add(new Animal()); // Ошибка компиляции } List<Dog> dogs = new ArrayList<>(); processAnimals(dogs); // Это разрешено благодаря <? extends Animal>
Таблица сравнения инвариантности и ковариантности (с учетом подстановочных типов):
| Свойство | Инвариантность (без wildcards) | Ковариантность (с <? extends>) |
Контравариантность (с <? super>) |
|---|---|---|---|
List<A> |
Может присвоить только List<A> |
Может присвоить List<B> (B extends A) |
Не может присвоить List<B> (B extends A) |
| Добавление | Разрешено | Не разрешено | Разрешено (с ограничениями) |
| Чтение | Разрешено | Разрешено | Разрешено (возвращает Object) |
Ковариантность делает API более гибким для чтения данных из коллекций или источников типов, которые являются подтипами ожидаемого типа.