一.泛型的定义
1.泛型是定义一种模板,ArrayList<T>
为用到的类创建ArrayList<类型>
ArrayList<String> strList = new ArrayList<String>();
编译器针对类型检查
strList.add("hello");
strList.add(new Integer(123)); compile error!
2. 泛型的继承关系。Arraylist<T>实现了List<T>接口
List<String> list = new ArrayList<String>();可以向上转型
不能把 ArrayList<Integer>向上转型为ArrayList<Number>或List<Number>
二.使用泛型时,把泛型参数<T>替换为需要的class类型:
List<String> list = new ArrayList<String>();
可以省略编译器能自动推断的类型:
List<String> list = new ArrayList<>();
不指定泛型参数类型,编译器会给出警告,且只能将T视为Object类型。
三.编写泛型
泛型类一般用在集合类中ArrayList<T>
编写泛型时,需要定义泛型类型<T>
public class Pair<T>{..}
静态方法不能引用泛型类型<T>,必须定义其他<K>来实现“”泛型“”
public static <K> Pair<K> create(K first,K last){...}
泛型可以同时定义多种类型<T,K>
public class Pair<T,K>{...}
四.擦拭法
擦拭法:编译器把类型<T>视为Object
编译器根据<T>实现安全的强制转型
擦拭法的局限:
1. <T>不能是基本类型,例如int
Object字段无法持有基本类型
2. 无法获取带泛型的class
所有的泛型实例,无论T的类型是什么,都返回同一个class
Pair<String>与Pair<Integer> 都是同一个class
无法判断泛型的class,if(s instanceof Pair<String>.class){
}
3. 不能实例化T类型,因为擦拭后实际上才是new Object()
实例化T类型必须借助Class<T>
public Pair(Class<T> clazz){
first = clazz.newInstance();
last = clazz.newInstance();
}
泛型方法要防止重复定义方法,例如:public boolean equals(T obj)
4.子类可以获取父类的泛型类型<T>
五,extends
使用类似<? extends Number> 通配符作为方法参数时表示:
方法内部可以调用获取Number引用的方法
Number n = obj.getX()
方法内部无法调用传入Number引用的方法(null除外):
obj.setxx(Number n)
使用类似<T extends Number>定义泛型类时表示:
泛型类限定为Number或Number的子类。
六. super通配符
使用<? super Integer>使方法接收所有泛型类型为Integer或Integer超类的Pair类
可以调用obj.setxx(Integer n)
方法内部无法调用获取Integer引用的方法
Integer n = obj.getxx()......因为无法知道获得的是什么类型,可能不是integer类型。
七.