1. 泛型的好处
- 减少了cast带来的运行时异常,
使算法和框架更为通用,减少了冗余代码
2. 泛型的使用
泛型有三种使用方式:泛型类、泛型接口、泛型方法。
- 泛型类,是在实例化类的时候指明泛型的具体类型;
- 泛型方法,是在调用方法的时候指明泛型的具体类型。
2.1 泛型类
java中常见的泛型类有:ArrayList、Set、Map等
//此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型
//在实例化泛型类时,必须指定T的具体类型
public class Generic<T>{
//key这个成员变量的类型为T,T的类型由外部指定
private T key;
public Generic(T key) { //泛型构造方法形参key的类型也为T,T的类型由外部指定
this.key = key;
}
public T getKey(){ //泛型方法getKey的返回值类型为T,T的类型由外部指定
return key;
}
}
注意:如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。
public static void main(String[] args){
Genericity g = new Genericity(10);
g.setT(false);
g.setT("Hello World!");
g.setT(g);
}
2.2 泛型接口
与泛型类的使用基本类似
2.3 泛型方法
在方法返回值类型之前声明是否为泛型方法,用<T>
、<T, E>
、<T extends Comparable<? super T>>
等方式表示。比如:
public <T> void genericity(T t){}
- 所有泛型方法声明都有一个类型
参数声明
部分(由尖括号分隔),该类型参数声明部分在方 法返回类型之前。- 泛型方法体的声明和其他方法一样。注意类型参数
只能代表引用型类型
(只能是类),不能是基本类型
(比如int 、double)。
Arrays中的泛型方法:
public static <T extends Comparable<? super T>> void parallelSort(T[] a) {
int n = a.length, p, g;
if (n <= MIN_ARRAY_SORT_GRAN ||
(p = ForkJoinPool.getCommonPoolParallelism()) == 1)
TimSort.sort(a, 0, n, NaturalOrder.INSTANCE, null, 0, 0);
else
new ArraysParallelSortHelpers.FJObject.Sorter<T>
(null, a,
(T[])Array.newInstance(a.getClass().getComponentType(), n),
0, n, 0, ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?
MIN_ARRAY_SORT_GRAN : g, NaturalOrder.INSTANCE).invoke();
}
3. 通配符
- <? extends T> 上界为T
- <? super T> 下界为T
- <E extends Comparable> : 类型 E 必须实现 Comparable 接口,并且这个接口的类型是 E
- <T extends Comparable<? super T>>:T的父类实现了Comparable接口即可
- 使用泛型进行排序
//使用Comparable接口确保E能够进行比较
public static <E extends Comparable<E>> void bubbleSort(E[] a) {
int n = a.length;
for(int i=0; i<n-1; i++){
for(int j=0; j<n-1; j++){
//使用compareTo()方法进行比较
if(a[j].compareTo(a[j+1]) > 0){ //为什么可以使用接口的compareTo()方法,
//因为大部分类都已经实现了Comparable接口,否则自己直接在E中实现Comparable接口即可
E temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
}