基础
泛型是一种模版代码技术
例如:
List<String> list=new ArrayList<>();
可以通过泛型指定集合里面的数据类型。
擦拭法
Java泛型采用擦拭法实现。所谓擦拭法是指,虚拟机对泛型其实一无所知,所有的工作都是编译器做的。
在编译的时候其实会把泛型类型进行擦除,使用的都是Object类型,到需要使用的时候再强制类型转换。
Java的泛型是由编译器在编译时实行的,编译器内部永远把所有类型T视为Object处理,但是,在需要转型的时候,编译器会根据T的类型自动为我们实行安全的强制转型。
比如编译器看到的代码,就是带泛型的,而虚拟机看到的代码,就是直接将泛型替换成Object的。
验证:可以尝试获取带泛型的Class,不同泛型类型情况下,获取到的Class是一样的,说明Class无法携带泛型。
泛型不能是基本数据类型,因为编译器默认是把泛型当成Object使用,而基本数据类型不是Object的子类。
类型转换
泛型内,可以将类上转型;但是不可以将泛型向上转型,可能会出现类型转换异常。(系统也禁止)并且假如泛型类型要求是一个具体的类,那么不可以传入它的子类,只能按照对应的类型进行传入,所以需要extends通配符来实现可传入子类。
使用<? extends Number>的泛型定义称之为上界通配符(Upper Bounds Wildcards),即把泛型类型T的上界限定在Number了。
使用extends通配符表示可以读,不能写。
Pair<? super Integer>表示,方法参数接受所有泛型类型为Integer或Integer父类的Pair类型。
因此,使用<? super Integer>通配符表示:
- 允许调用set(? super Integer)方法传入Integer的引用;
- 不允许调用get()方法获得Integer的引用。
唯一例外是可以获取Object的引用:Object o = p.getFirst()。
何时使用extends,何时使用super?为了便于记忆,我们可以用PECS原则:Producer Extends Consumer Super。
即:如果需要返回T,它是生产者(Producer),要使用extends通配符;如果需要写入T,它是消费者(Consumer),要使用super通配符。
可以声明带泛型的数组,但不能用new操作符创建带泛型的数组,必须通过强制转型实现带泛型的数组