泛型
一、理论基础
概念:
jdk1.5出现的安全机制;
编译时:泛型技术是给编译器使用的技术,确保类型安全。
运行时:会将泛型去掉,生成的class文件时不带泛型的-- 成为泛型擦除
(1)为什么会擦除?
为了兼容运行的类加载器,(jdk1.5之后引入了泛型,但与之对应的运行的类加载器没有升级)
当然,并不是每一个泛型参数被擦除类型后都会变成 Object 类。对于限定了继承类的泛型参数,经过类型擦除后,所有的泛型参数都将变成所限定的继承类。也就是说,Java 编译器将选取该泛型所能指代的所有类中层次最高的那个,作为替换泛型的类。
(2)什么是泛型补偿/转换?
在运行时,通过获取元素的类型进行转换的工作,无需使用者再强制转换。
(编译器只做检查,编译后类型被擦除,所以泛型内部存的还是Object, 为了避免强转,在类加载器基础上引入补偿机制,根据指定的元素类型,对其进行一次转换。)
好处:
- 将运行时期的问题classCastException转到了编译时期。
- 避免了强制转换的麻烦
既然泛型会被类型擦除,那么我们还有必要用它吗?
我认为是有必要的。Java 编译器可以根据泛型参数判断程序中的语法是否正确。举例来说,尽管经过类型擦除后,ArrayList.add 方法所接收的参数是 Object 类型,但是往泛型参数为 Integer 类型的 ArrayList 中添加字符串对象,Java 编译器是会报错的。
ArrayList<Integer> list = new ArrayList<>();
list.add("0"); // 编译出错
核心思想:
把一个集合的内容限制为一个特定的数据类型;
使用场景:
操作的引用数据类型不确定的时候。就用<>, 将要操作的引用数据类型传入即可。
<> 就是一个用于接收具体引用数据类型
使用泛型后,不需要写类型强转的代码了,如果类型不对也会有提示且编译失败,现在知道的多一点了, 本质上类型强转的工作还是必须要做的,只是不是有开发人员来做了,由编译器来做,并且编译器会擦除掉对应的泛型信息,使用合适的父类型来代替,可能是Object类也可能是声明泛型时指定的继承的类
自动装箱:
基本类型-->包装类型
[Wrapper].valueOf(如 Integer.valueOf)
自动拆箱:
包装类型-->基本类型
[Wrapper].[primitive]Value(如 Integer.intValue)