什么是泛型
泛型是jdk5引入的类型机制,就是将类型参数化,泛型作为一种安全机制而产生
泛型在本质上是指类型参数化。所谓类型参数化,是指用来声明数据的类型本身,也是可以改变的,它由实际参数来决定。在一般情况下,实际参数决定了形式参数的值。而类型参数化,则是实际参数的类型决定了形式参数的类型。
使用泛型的优势
1、可读性,从字面上就可以判断集合中的内容类型;
2 、类型检查,避免插入非法类型。
3 、获取数据时不在需要强制类型转换。
泛型类
所谓泛型类generic class就是具有一个或多个类型参数的类
public class 类型名<泛型名称列表>{ }
带两个类型参数的泛型类
如果引用多个类型,可以使用逗号分隔:<S, D>
类型参数名可以使用任意字符串,建议使用有代表意义的单个字符,以便于和普通类型名区分,如:T代表type,有源数据和目的数据就用S/D,子元素类型用E等。当然,你也可以定义为XYZ,甚至xyZ。
泛型中的类型参数严格说明集合中装载的数据类型是什么和可以加入什么类型的数据,记住:Collection 和 Collection 是两个没有转换关系的参数化的类型
集合类中定义范型
范型只能使用引用类型,而不能使用基本类型,即:List是错误的
保持良好的编程风格,尽量使用范型
有界类型
public class MyClass{ }表示允许传入给T的类型必须是Number类型的子类型或者Number类型
MyClass mc=new MyClass(); 语法正确,因为Integer是Number的子类型
MyClass mc=new MyClass<>(); 语法错误,因为String不是Number类型
接口和类都可以用来做上界。
类充当上界public class Oper
接口充当上界class Stats这里需要注意:针对上界接口使用的关键字仍然是extends而非implements
泛型方法
所谓泛型方法,就是带有类型参数的方法,它既可以定义在泛型类中(例如public void show(T aa),在使用泛型上没有任何特殊语法要求),也可以定义在普通类中(需要自定义参数类型,那么把泛型参数放在方法上就可以了,就是放在返回值类型之前,例如public void show(T aa)), 静态方法不能访问类的泛型,如果需要泛型只能在方法上使用泛型,例如public static void show(T aa)
在泛型类中包含泛型的方法
泛型类的继承
泛型类也是可以继承的,任何一个泛型类都可以作为父类或子类
不过泛型类与非泛型类在继承时的主要区别在于:泛型类的子类必须将泛型父类所需要的类型参数,沿着继承链向上传递。这与构造方法参数必须沿着继承链向上传递的方式类似。
泛型的实现原理
实际上,从虚拟机的角度看,不存在泛型概念。
泛型是运用在编译时期的技术:编译时编译器会按照<类型名>的类型对容器中的元素进行检查,检查不匹配,就编译失败。如果全部检查成功,则编译通过,但,编译通过后产生的.class文件中并没有<类型名>这个标识,即类文件中没有泛型,这就是泛型的擦除。
一句话总结就是:在.java文件运用泛型技术时,编译器在文件编译通过后自动擦除泛型标识
由于泛型的擦除,类文件中没有泛型机制,同时也没有使用向下类型转换,那么为何运行时无异常?
这是由于泛型的补偿
编译器在擦除泛型后,会自动将类型转换为原定义的"泛型",这样就不必再做向下类型转换了。
泛型的擦除和补偿这两个机制都是编译器内部自动完成的,了解其原理即可。
泛型的局限性
不能使用基本类型
不能使用泛型类异常
不能使用泛型数组