Java语言中的协变和逆变(zz)

转载声明:

本文转载至:http://swiftlet.net/archives/1950 

协变和逆变指的是宽类型和窄类型在某种情况下的替换或交换的特性。简单的说,协变就是用一个窄类型替代宽类型,而逆变则用宽类型覆盖窄类型。

协变

在Java中协变的例子非常常见,例如,面向对象的多态,以及数组的协变特性,下面看一下协变的例子:

public class Test  
{  
    public static void main(String[] args)  
    {  
        Number num1 = new Integer(0);  
        Number[] num2 = new Integer[10];  
    }  
}  

而在泛型是不支持协变的,看下面的代码:

public class Test  
{  
    public static void main(String[] args)  
    {  
        List<Object> list = new ArrayList<String>();//编译错误  
        list = new ArrayList<Object>();  
    }  
}  

虽然泛型不支持协变的,但是可以通过通配符进行模拟:

public class Test  
{  
    public static void main(String[] args)  
    {  
        List<? extends Object> list = new ArrayList<String>();  
    }  
}  

注意:? extends Object的含义是:运行Object的子类,也包括Object,作为泛型参数。

逆变

在Java中不允许将父类变量赋值给子类变量。泛型自然也不支持逆变。但是在泛型中可以通过通配符进行模拟,如下例子:

public class Test  
{  
    public static void main(String[] args)  
    {  
        List<? super Integer> list = new ArrayList<Number>();  
    }  
}