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