泛型的逆变和协变是什么?
请解释Java泛型中**逆变(Contravariance)和协变(Covariance)**的概念。说明数组的协变与泛型不变性的区别,以及PECS原则如何帮助设计灵活的API。
回答
小字辈
协变(Covariance):
- 如果A是B的子类,那么Container也是Container的子类
- Java数组是协变的:Integer[] is Object[](运行时报错)
- 泛型本身是**不变(Invariant)**的:List不是List的子类型
- 可以通过
? extends T实现协变:List<? extends Number>可接收List
逆变(Contravariance):
不变性:List和List没有继承关系,保证类型安全
为什么数组协变? 是历史设计决策,Java 1.0时还没有泛型。数组协变破坏了类型安全(运行期ArrayStoreException)。
PECS:Producer用extends(协变),Consumer用super(逆变)。
示例:Java Collections.copy(List<? super T> dest, List<? extends T> src) 同时使用了逆变和协变。