泛型

一、理论基础

概念:

jdk1.5出现的安全机制;

 

编译时:泛型技术是给编译器使用的技术,确保类型安全。

运行时:会将泛型去掉,生成的class文件时不带泛型的-- 成为泛型擦除

 

(1)为什么会擦除?

为了兼容运行的类加载器,(jdk1.5之后引入了泛型,但与之对应的运行的类加载器没有升级)

当然,并不是每一个泛型参数被擦除类型后都会变成 Object 类。对于限定了继承类的泛型参数,经过类型擦除后,所有的泛型参数都将变成所限定的继承类。也就是说,Java 编译器将选取该泛型所能指代的所有类中层次最高的那个,作为替换泛型的类。

 

(2)什么是泛型补偿/转换?

在运行时,通过获取元素的类型进行转换的工作,无需使用者再强制转换。

(编译器只做检查,编译后类型被擦除,所以泛型内部存的还是Object, 为了避免强转,在类加载器基础上引入补偿机制,根据指定的元素类型,对其进行一次转换。)

 

好处:

  1. 将运行时期的问题classCastException转到了编译时期。
  2. 避免了强制转换的麻烦

 

既然泛型会被类型擦除,那么我们还有必要用它吗?

我认为是有必要的。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)