泛型表示:<T,E,K,V>
泛型方法
使用 声明类型
泛型类
java
public class User<K,V>{
}
只能在类上声明定义泛型参数,用于继承类/实现接口类型上、以及类方法上使用。
泛型类 | 泛型方法 | |
---|---|---|
定义 | 在类名后面定义泛型参数 | 在方法返回值前面定义泛型参数 可以定义在泛型类中也可以定义在普通类中 |
使用 | 实例化时指定具体类型 | 调用时推导类型 |
静态方法 | 不能访问泛型参数 | 可以访问泛型参数 |
使用场景 | 泛型参数需要在多个方法或成员属性间扭转 | 泛型参数只需作用与某个方法 |
类型擦除
向低版本兼容。只支持引用数据类型,最终泛型会被擦除成具体类型。
如:List、List 运行时都会变成List。
List 运行时无法判断T的类型,T data = new T(); 编译会错误。
Java泛型弊端
- 不支持基本类型
- 只有原始类型的class
- 不能实例化类型参数
- 不能实例化泛型数组
泛型变型
一般用于方法上。

- 协变&上界
协变不能新增元素,只读不写。
java
public class Animal {
}
public class Cat extend Animal {
}
public class Dog extend Animal {
}
// ? 通配符
List<? extends Animal> list;
- 逆变&下界
逆变能够新增元素,只写不读。
读取元素不能保证元素是什么类型,只能用Object来表示。
java
void func(List<? super Dog> dest,List<? extends Dog> src);
JDK中Collections类中copy方法:
java
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
int srcSize = src.size();
if (srcSize > dest.size())
throw new IndexOutOfBoundsException("Source does not fit in dest");
if (srcSize < COPY_THRESHOLD ||
(src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i<srcSize; i++)
dest.set(i, src.get(i));
} else {
ListIterator<? super T> di=dest.listIterator();
ListIterator<? extends T> si=src.listIterator();
for (int i=0; i<srcSize; i++) {
di.next();
di.set(si.next());
}
}
}
- 不变
泛型默认是不变的,禁止协变。
ps:数组支持协变。
java
List<Integer> list = new ArrayList<Integer>();
List<Integer> list = new ArrayList<Long>(); //编译报错