泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。 比如我们要写一个排序方法,能够对整型数组、字符串数组甚至其他任何类型的数组进行排序,我们就可以使用 Java 泛型。
Java 中的泛型基本上都是在编译器这个层次来实现的。在生成的 Java 字节代码中是不包含泛型中的类型信息的。使用泛型的时候加上的类型参数,会被编译器在编译的时候去掉。如在代码中定义的 List<Object>和 List<String>等类型,在编译之后
都会变成 List。 这个过程就称为类型擦除。
public static void main(String[] args) {
ArrayList<String> list1 = new ArrayList<String>();
list1.add("abc");
ArrayList<Integer> list2 = new ArrayList<Integer>();
list2.add(123);
//泛型类型String和Integer都被擦除掉了,只剩下原始类型
System.out.println(list1.getClass() == list2.getClass());
}
public static void main(String[] args) throws Exception {
ArrayList<Integer> list = new ArrayList<Integer>();
//这样调用 add 方法只能存储整形,因为泛型类型的实例为 Integer
list.add(1);
//Integer泛型实例在编译之后被擦除掉了,只保留了原始类型。
list.getClass().getMethod("add", Object.class).invoke(list, "asd");
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
}
JVM并不知道泛型的存在,因为泛型在编译阶段就已经被处理成普通的类和方法;
原始类型 就是擦除去了泛型信息,最后在字节码中的类型变量的真正类型,无论何时定义一个泛型,相应的原始类型都会被自动提供,类型变量擦除,并使用其限定类型(无限定的变量用Object)替换。
处理机制是通过类型擦除,擦除规则:
- 若泛型类型没有指定具体类型,用Object作为原始类型;
- 若有限定类型< T exnteds XClass >,使用XClass作为原始类型;
- 若有多个限定< T exnteds XClass1 & XClass2 >,使用第一个边界类型XClass1作为原始类型;
//使用FutureTask 作为原始类型
class Test<T extends FutureTask & RunnableFuture> {}
网友评论