对于泛型,如果我们拿Object去写的话,并不通用,就比如你写一个栈,拿到返回值必须强转(从Object强转到你想要的类型),如果有多个返回值,那就得强转多次,所以这个方法行不通,于是引入了泛型:
一、泛型的意义
1、可以对类型进行自动检查 =====> 检查并不是替换(编译期间进行检查,放入元素的时候检查)
2、可以自动对类型进行转换 =====> 转换也不是替换(拿出元素的时候自动转换)
T:类型占位符 表示该类是一个泛型类
二、泛型类型怎么编译的?
类型的擦除机制: 擦除到Object(向上擦除),在编译器编译期间把泛型全部擦除为Object类型
三、泛型的上界:(泛型没有下界)
class GenericAlg<T extends Comparable<T>> {
public T findMaxVal(T[] array) { //找到数组中的最大值
T max = array[0];
for (int i = 0; i < array.length; i++) {
if(array[i].compareTo(max) > 0) {
max = array[i];
}
}
return max;
}
}
<T extends Comparable<T>>
这样的话指定擦除到Comparable就停止了,否则的话,擦除到Object,但Object并没有实现Comparable接口,于是便不能比较了;上界就是规定了擦除的位置;
四、通配符?:
Integer ArrayList<Integer>
Number ArrayList<Number>
Object ArrayList<Object>
这些不构成继承关系,类之间有继承关系,但他们的泛型类型之间并不构成继承关系
也有擦除机制,也是擦除到Object
不知道传入参数类型,通通接收
//写一个通用的算法:打印集合ArrayList内的所有元素
class GenericAlg3 {
public static <T> void printList1(ArrayList<T> list) {
for (T obj : list) {
System.out.print(obj + " ");
}
System.out.println();
}
//? :通配符 擦除机制 ==== 》Object
public static void printList(ArrayList<?> list) {
for (Object obj : list) {
System.out.print(obj + " ");
}
System.out.println();
}
}
通配符的应用:
因为基类实现的接口,派生类用的时候没必要在实现一次。
通配符的上界、下界;
(上界一般用不到,上界主要用来写入,一般用作库的开发(如DK源码))
(下界主要用来读取)
/**
* ArrayList<? extends T> 上界 主要用来写入
* @param list
* @param <T>
* @return
*/
public static <T extends Comparable<T>> T findMaxVal(ArrayList<? extends T> list) {
T max = list.get(0);
for (int i = 0; i < list.size(); i++) {
if(max.compareTo(list.get(i)) < 0) {
max = list.get(i);
}
}
return max;
}
/**
* 通配符的下界:找到是不是有T的基类实现了Comparable接口
* 主要用来读取
*/
public static <T extends Comparable<? super T>> T findMaxVal2(ArrayList<T> list) {
T max = list.get(0);
for (int i = 0; i < list.size(); i++) {
if(max.compareTo(list.get(i)) < 0) {
max = list.get(i);
}
}
return max;
}
五、注意:
1、泛型数组不能new,可以 this.elem = (T[])new Object[size];不能 new T[]
2、不能new泛型类型的对象 不能 T o = new T();
3、不能new泛型类型的对象数组 (如果能那就写Object就可以了,然后就又回去了)
4、不能用简单类型作为泛型类型的参数,
5、一定要加泛型类型的参数,否则就是Object了,又回去了
6、在静态方法中,类不能使用泛型类型的参数,因为静态方法不依赖于对象,如果不依赖于对象,就不知道这个T是什么类型,那编译的时候就没法(静态方法中T:会通过实参的类型推演出泛型类型;也可以传参数的时候添上类型)
class GenericAlg2 {
/**
* 泛型方法
* @param array
* @param <T>
* @return
*/
public static <T extends Comparable<T>> T findMaxVal(T[] array) {
T max = array[0];
for (int i = 0; i < array.length; i++) {
if(array[i].compareTo(max) > 0) {
max = array[i];
}
}
return max;
}
}