学习泛型的时候遇到了协变和逆变的概念,其实从某种程度上来说,这是可以略过的,这种概念的东西乍一看很容易让人不知所云。之所以说可以略过,是因为协变和逆变是一个单独存在的概念,然后恰巧在泛型的某些情况中有所体现。
更多的时候,大家更喜欢使用数组举例,然后说数组是协变的。本文将先讲述协变和逆变的概念,然后再举出数组的协变的例子,然后是泛型的协变和逆变的例子。
协变和逆变是函数中的概念
首先设计到一个函数的概念,协变和逆变是表示 函数变量关系与函数关系的特性表述。
比如 1<2 , 然后 函数f(x)=x+1,那么 f(1)< f(2),再进一步拓展假如 1<=2,并且f(1)<=f(2),那么我们就说 f(x) 是 协变 的。
再比如,1<2,f(x)=-x,这个时候就有 f(1) >f(2) ,再进一步扩展,1<=2,并且f(1)>=f(2),那么我们就说f(x)是逆变的。
数组就像一种函数,变量是某种Java类或者接口,数组是协变的
在 Java 中,向上转化和向下转化都是基于具体类或者接口来说的,比如Integer、Number、Object,那么Integer[]是不是一个单独的类型呢?是的,数组是新组合起来的类型,即由某种类或接口产生了一种变化,等同于数学中称之为函数的东西。
比如这里,Integer 是 Number 的子类,那么经过一个变化之后,比如 Integer[]和Number[]之后,二者会是什么关系呢?如下代码:
@Test
public void test(){
Number[] array1=new Number[1];//合法
Number[] array2=new Integer[1];//合法
//Integer[] array3=new Number[1];//编译报错
}
Java 多态中有一个子类概念,显然,new Number[1] 在这里类似于 Number[] 的子类,然后第三行是编译报错,如果把数组看做一个函数,那么满足 x<=y , f(x)<=f(y),所以数组是协变的,第三行表示数组不是逆变的。
泛型是不可变的
上文已经说了,协变与逆变的概念,以及数组是协变的。
泛型是不可变的,即 ArrayList<Number>和ArrayList<Integer>并不具有 Number与Integer那样的关系,这是因为泛型是在编译期检测类型合法性的,而在实际运行期类型被擦除了,所以在泛型看来 ArrayList<Number> 和 ArrayList<Integer> 是两种不同的类型。
如下代码会编译报错:
@Test
public void test1(){
ArrayList<Number> list=new ArrayList<Integer>();//编译报错
}
泛型实现协变和逆变的特性-其他形式的泛型-彩蛋
不好意思哦,其他形式的泛型“犹抱琵琶半遮面”,下一篇见哦~
本文解释了协变和逆变的基本概念,并通过数组和泛型的实例进行说明。介绍了这两种概念如何应用于Java中的数组及泛型,展示了它们在不同上下文中的行为表现。
2425

被折叠的 条评论
为什么被折叠?



