泛型上下边界
Producer Extends, Consumer Super
<? super T>:表示类型的下界是 T,可以put元素,get拿的类型是Object
<? extends T>:类型的上界是 T,只能get,拿到是T类型
List< F> ll = new ArrayList<>();
ll.add(new C());
ll.add(new F());
F f = ll.get(0); //默认就是F
List< ? super F> ll2 = new ArrayList<>();
ll2.add(new C());
ll2.add(new F());
Object object = ll2.get(0); //类型是Object
List< ? extends F> ll3 = new ArrayList<>();
//ll3.add(new C());//报错不能放
//ll3.add(new F());//报错不能放
F f1 = ll3.get(0);
泛型的类型擦除
这就是 Java 泛型的类型擦除造成的,因为不管是 ArrayList<Integer> 还是 ArrayList<String>,在编译时都会被编译器擦除成了 ArrayList。Java 之所以要避免在创建泛型实例时而创建新的类,从而避免运行时的过度消耗。
那么如何在运行期间获取泛型信息呢:
自定义的类假如写死了泛型那么是会保留泛型信息的。
Map<String, Integer> map = new HashMap<String, Integer>() {};
其中最关键的差别是本节的变量声明多了一对大括号。其实是创建了一个匿名内部类。这个类是 HashMap 的子类,泛型参数限定为了 String 和 Integer。
其实在“泛型擦除”一节,我们已经提到,Java 引入泛型擦除的原因是避免因为引入泛型而导致运行时创建不必要的类。那我们其实就可以通过定义类的方式,在类信息中保留泛型信息,从而在运行时获得这些泛型信息。
简而言之:Java 的泛型擦除是有范围的,即类定义中的泛型是不会被擦除的。
网友评论