1. 数组协变
数组协变本质是多态,即用声明的父类变量或接口,接收子类对象。请看下面的Demo:
class Animal{ @Override public String toString() { return "Animal"; } } class Person{ @Override public String toString() { return "Person"; } } public class GenericTypeTest { @Test public void test01() { Object[] animals = new Animal[3]; animals[0] = new Animal(); //编译通过 animals[1] = new Person(); //编译通过 System.out.println(Arrays.toString(animals)); } }
在上述Demo中,声明了元素为Object的数组,但实际对象引用类型为Animal(数组协变)。此时,设置元素引用时,animal[0]设置成new Animal()显然时没问题的。但是,在设置animal[1] = new Person()时,编译虽然通过,但是执行时会产生java.lang.ArrayStoreException,数组存储异常。
所以,即使使用Object[]变量接收,也无法存储非Animal的对象引用。
2. 泛型的上下限
package com.tca.thinkInJava.chap15.test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.Test; class Animal{ @Override public String toString() { return "Animal"; } } class Person{ @Override public String toString() { return "Person"; } } public class GenericTypeTest { @Test public void test02() { List<Object> animals = new ArrayList<Animal>();//编译报错 } }
在上述Demo中,我们声明List<Object>,但是不能接收ArrayList<Animal>的对象(编译报错),即泛型不存在协变现象。但是泛型的上下限可以解决此类问题。
package com.tca.thinkInJava.chap15.test; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.junit.Test; class Animal{ @Override public String toString() { return "Animal"; } } class Person{ @Override public String toString() { return "Person"; } } public class GenericTypeTest { @Test public void test02() { List<? extends Object> animals = new ArrayList<Animal>();//编译报错 } }使用List<? extends Object>,即只要继承于Object类的元素都可以被该变量接收或存储。此外,还有List<? super Animal>可以接收被Animal继承的所有父类对象。
public class GenericTypeTest { @Test public void test02() { List<? extends Object> animals = new ArrayList<Animal>(); } @Test public void test03() { List<? super Animal> Objs = new ArrayList<Object>(); } }