数组的协变与泛型上下限

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

猜你喜欢

转载自blog.csdn.net/tca0819/article/details/80559512