Java 泛型
引言
泛型是 jdk1.5 的新特性,在日常的集合使用中经常会接触到泛型,本文力求较深入、全面,且简洁地总结一下这个特性。
泛型作用
使用泛型集合,可以将集合里的元素限定为一个特定的类型,以保证集合里的类型安全,把可能出现在运行期的错误提前到了编译期,且从集合中取出元素时不必再进行强制类型转换;
泛型擦除
泛型在编译阶段被擦除,也就是说编译后的字节码走的仍然是老套路,数组集合里装的都是 Object类,调用是补上强制类型转换。擦除,使泛型可以与没有使用泛型的代码随意互用;
public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
ArrayList<Integer> arrayList = new ArrayList<>();
arrayList.getClass().getMethod("add", Object.class).invoke(arrayList, "a");
System.out.println(arrayList.get(0)); //a
}
泛型的不可变性
String[] 是 Object[] 的子类型,但 List<String> 不是 List<Object> 的子类型, List<Object>里既能放 String,也能放其他继承了 Object 的类,但是 List<String> 里只能放 String 的类;
Object[] object = new Integer[2]; //ok
List<Object> arrayList1 = new ArrayList<Integer>(); //Incompatible types
泛型类
当类中要操作的引用数据类型不确定的时候,不再定义 Object ,而是定义泛型来完成扩展;
public class Utils<T> {
private T t;
public T getT() {
return t;
}
public void setT(T t) {
this.t = t;
}
}
泛型方法
如 List 的 toArray 方法,表示将 List 放进 T 类型的数组 a 中,并返回 a;另外,在类中定义静态泛型方法时,不能访问类上的泛型;
public static void main(String[] args) {
public interface List<E> extends Collection<E> {
<T> T[] toArray(T[] a);
}
Demo<String> demo = new Demo<String>();
demo.show(2); //编译错误
}
class Demo<T> {
public void show(T t) {
System.out.println(t);
}
//泛型方法,不受泛型类的泛型变量影响
public <E> void make(E e) {
System.out.println(e);
}
}
泛型限定
通过使用通配符 “?”限定类型:
? extends E : E 类型或者 E 类型的子类,限定上限;
? super E : E 类型或者 E 类型的父类,限定下限;