1. 程式人生 > >Java語言中的協變和逆變

Java語言中的協變和逆變

協變和逆變指的是寬型別和窄型別在某種情況下的替換或交換的特性。

  • 協變就是用一個窄型別替代寬型別
  • 逆變則用寬型別覆蓋窄型別。

協變

在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>();
    }
}

注意:? super Integer的含義是:支援Integer的父類,也包括Integer類,作為泛型的引數。

泛型中的 <? extends E><? super E>的含義

  • <? extends E>指泛型引數支援E及E的子類
  • <? super E>指泛型引數支援E及E的父類

程式碼示例:

有三個類Fruit、Apple和Orange,Fruit是Apple和Orange的父類。

class Fruit{

}

class Apple extends Fruit{

}
class Orange extends Fruit{

}

// list可以包含任何Fruit的子類和Fruit本身
List<? extends Fruit> list = new ArrayList<Orange>();   
// list2可以包含任何Orange的父類及Orange本身
List<? super Orange> list2 = new ArrayList<Fruit>();