Ковариантность
Ковариантность в Java - это свойство обобщённых типов,
при котором List<Integer> может быть
присвоен переменной типа List<? extends Number>.
Другими словами, если класс B является наследником
класса A, то объект типа List<B>
можно использовать там, где ожидается
List<? extends A>. Ковариантность
достигается с помощью wildcard-параметра с ключевым
словом extends. Такой параметр называется
ковариантным wildcard. Из коллекции, объявленной
как List<? extends A>, можно
безопасно читать элементы типа A, но нельзя
добавлять новые элементы (кроме null), так как
компилятор не знает точный тип элементов.
Синтаксис
Type<? extends Parent> variable = new Type<Child>();
Пример
Давайте создадим список целых чисел и присвоим его переменной с ковариантным wildcard-типом, а затем прочитаем элементы:
import java.util.List;
public class Main
{
public static void main(String[] args)
{
List<Integer> ints = List.of(1, 2, 3, 4, 5);
List<? extends Number> nums = ints;
Number first = nums.get(0);
System.out.println(first);
}
}
Результат выполнения кода:
1
Пример
Давайте попробуем добавить элемент в список с ковариантным wildcard-типом и убедимся, что компилятор запрещает такую операцию:
import java.util.ArrayList;
import java.util.List;
public class Main
{
public static void main(String[] args)
{
List<Integer> ints = new ArrayList<>();
List<? extends Number> nums = ints;
// nums.add(1); // compile error
System.out.println("Cannot add to covariant list");
}
}
Результат выполнения кода:
"Cannot add to covariant list"
Пример
Давайте напишем метод, который принимает ковариантный список чисел и суммирует все элементы:
import java.util.List;
public class Main
{
public static double sum(List<? extends Number> nums)
{
double res = 0;
for (Number num : nums)
{
res += num.doubleValue();
}
return res;
}
public static void main(String[] args)
{
List<Integer> ints = List.of(1, 2, 3, 4, 5);
System.out.println(sum(ints));
}
}
Результат выполнения кода:
15.0
Смотрите также
-
wildcard-extends,
который задаёт ковариантный wildcard -
contravariant,
который описывает контравариантность -
invariant,
который описывает инвариантность -
wildcard,
который описывает wildcard-параметры