下午看了effective java 讲到泛型,查看了网上的相关资料,对一些比较模糊的地方做一下总结
1.定义泛型(类后方法前)
public class TestClassDefine<T, S extends Object>{}//T,S随意定义,但是一般会使用T,S
public <T, S extends Object> T testGenericMethodDefine(T t, S s){}
2.泛型实例化
2.1声明类或实例化对象时
List<String> list;
list = new ArrayList<String>;
2.2继承或实现接口时
public class MyList<E> extends ArrayList<E> implements List<E> {...}
3 通配符,当泛型赋值时,赋值的类型不确定的时候,我们用通配符 ? 代替
List<?> unknownList;
List<? extends Number> unknownNumberList;
List<? super Integer> unknownBaseLineIntgerList;
? 通配符类型
? extends 表示类型的上界,表示参数化类型的可能是T 或是 T的子类
? super 表示类型下界(Java Core中叫超类型限定),表示参数化类型是此类型的超类型(父类型),直至Object
存取原则和PECS法则
◆ 如果你想从一个数据类型里获取数据,使用 ? extends 通配符
因为这里限定了?类型的上界,所有?指向的具体类型是不确定的,所以不能将?通配符指向的类型存到具体的数据结构中。
如:
List<? extends Number> list = new ArrayList<Integer>();
//list.add(1);
这句话是报错的,因为我们只知道上限是Number,不知道子类是啥,所以无法添加,甚至你new Number() 也是无法添加的,所以 ***? extends*** 不支持添加,只支持读取
◆ 如果你想把对象写入一个数据结构里,使用 ? super 通配符
假设 ? super T
这里因为我们知道了?通配符的下限为T,所以我们知道所有?都是T的父类(抽象),所以我们能往具体的数据结构里添加T类型及其子类,因为T及其子类的父类都是?,所以
List<? extends T> list = new ArrayList<Integer>();
T a = new T();
list.add(a);
是成立的
◆ 如果你既想存,又想取,那就别用通配符。
这PECS是指”Producer Extends, Consumer Super”,这个更容易记忆和运用