泛型类
语法:public class<T> {},泛形参数写在类名后面
泛型方法
语法:public <T> void show(T t){},泛型参数在方法返回值的前面
边界<? extends xxx> < ? super xxx>
<? extends xxx>
所描述的任何继承于xxx 的类,定义了一个上界,也就是 xxx 可以是继承结构图中顶端的类,当然也可以为xxx 的子类。
<? super xxx>
所描述的任何xxx 的基类,定义一个下界,也就是所代表的类最大值为xxx ,当然也可以xxx 的任何基类。
class Fruit{}
class Apple extends Fruit{}
class RedApple extends Apple{}
定一个List 引用 apples,泛型为
List<? extends Apple> apples = new ArrayList<RedApple>();
可以通过编绎阶段,但是当我们试图向apples 容器中添加 一个RedApple 对象时,
apples.add(new Apple());
编绎器报错,查看JDK List 部份原码如下:
public interface List<E> extends Collection<E> {
boolean add(E e);
//...
}
在原码中可以看到List 是一个泛型类,其中的add(E e) 方法中的形参为类中所定义的泛型参数,在apples 的容器中,定义的实际泛型为
<? extends Apple>
也就是所有继承于Apple 的子类,那么在List 中的Add 方法中的实参将变为
< ? extends Apple>
但是这里描述的只是一个范围,实际却不知道你要插入的确切类型,所以编绎报错,从而丧失了向apples 中插入。
对apples 稍作修改
List<? extends Apple> apples = Arrays.asList(new Apple(),new RedApple());
尝试从apples 容器中取出元素
Apple apple = apples.get(0);
编绎通过,成功从apples 中取出元素,查看Jdk 中List 类的 get() 方法 原码
E get(int index);
发现get 方法的形参是一个整形变量,和我们所定义的泛型参数没有联系,所以此方法可以正常使用,但却不能向apples 容中添加 任何的对象包括Object类型的
重新定义 apples
List<? super Apple> apples = new ArrayList<Apple>();
现在我们定义的泛型为
<? super Apple>
代表 apples 容器可以为任何 Apple 的基类,或者最起码为 Apple 类的容器,
apples.add(new Apple());
apples.add(new RedApple())
编绎通过,成功加入容器中,通过定义一个下界,重新获得向容器中插入元素的能力。