Java逆变(Covariant)和协变(Contravariant)

1. 定义

逆变和协变描述的经过类型变换后的类型之间的关系。假如AB表示类型,f表示类型变换,A ≤B表示A是B的子类型,那么

  • 如果A ≤Bf(A) ≤f(B),那么f是协变
  • 如果A ≤Bf(B) ≤f(A),那么f是逆变
  • 如果两者都不是,那么f不变
    这里的子类型并非是面向对象中继承关系中的子类型,它更多的是描述两个类型之间的兼容性。

2. 实例:泛型

考虑一个例子,假如f(A) = List<A>,且List声明如下:

class List<T> { ... }

那么f是逆变,还是协变,又或者是不变?如果是协变意味着List<String>List<Object>的子类型,如果是逆变意味着List<Object>List<String>的子类型:

ArrayList<String> strings = new ArrayList<Object>();   // error
ArrayList<Object> objects = new ArrayList<String>();  // error

在Java中显然两者都不成立,所以说f是不变,且f表示泛型,即Java泛型是不变。

2. 实例:数组

再举个例子,假如f(A) = A[], 那么f是逆变,还是协变,又或者是不变?如果是协变意味着String[]Object[]的子类型,如果是逆变意味着Object[]String[]的子类型:

Object[] objects = new String[1];

可以看出,在Java中数组是协变。

原文地址:https://www.cnblogs.com/kelthuzadx/p/11889096.html