原文参考:https://www.cnblogs.com/shan333/p/14462986.html
1、概念
泛型是Java语言中的一个重要特性,它允许在编译时确定数据类型,从而提高了代码的灵活性和安全性。泛型的本质是参数化类型,即所操作的数据类型被指定为一个参数(type parameter),这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
2、泛型特点
特点:(1)编译时即可检查,非运行时抛出异常;
(2)访问时不需要类型转换(拆箱);
(3)不同泛型之间不能相互赋值,泛型不存在多态。
举例:对于泛型特点(1)举个例子 : 没有使用泛型时的异常抛出
public class MyGenericTest {
public static void main(String[] args) {
List list =new ArrayList();
list.add(123);//添加Integer对象
list.add("zifu");//添加String对象
list.add(1.22);//添加Double对象
for(Object object: list) {
Double num = (Double)object;
System.out.println(num);
}
}
}
运行结果报错:Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double at MyGenerics.MyGenericTest.main(MyGenericTest.java:28)
分析一下:编译通过,但是运行提示异常,类型转换异常,就是String类型不能转换为Double类型。我们在使用 list.add() 方法时,根据提示知道凡是Object对象都可以添加进去,但是要使用的时候忘了添加过什么类型的对象进去,根据提示强转过,但是由于添加进去一些类型不同的,强转可以在编译时通过,运行时异常抛出了。
这里就可以体现泛型的好处之一了:防止类型转换异常,提高代码的安全性。
泛型特点(3)不同泛型之间不能相互赋值,举例
List<String> list =new ArrayList<String>();
List<Integer> list2 = list ;
泛型特点(3)泛型不存在多态,举例
3、泛型擦除
概念:类型擦除指的是通过类型参数合并,将泛型类型实例关联到同一份字节码上。编译器只为泛型类型生成一份字节码,并将其实例关联到这份字节码上。类型擦除的关键在于从泛型类型中清除类型参数的相关信息,并且再必要的时候添加类型检查和类型转换的方法。
简单理解:在编译期间,所有的泛型信息都会被擦除掉。例如代码中定义的List<Object>和List<String>等类型,在编译后都会变成List。JVM看到的只是List,而由泛型附加的类型信息对JVM来说是不可见的。
由于泛型擦除出现的错误举例:
报错原因:Erasure of method MyGeneric(ArrayList<String>) is the same as another method in type MyGeneric<T>,Erasure of method MyGeneric(ArrayList<Integer>) is the same as another method in type MyGeneric<T>
类型擦除的原因,擦除后 //方法重载,都变成了
public MyGeneric(ArrayList arrayList) {
}
完美解释此处问题,但是却勾起小伙伴的另外一个问题,类型擦除了,为什么不同泛型之间不能相互赋值!!
因为检查机制的存在,编译器的工作是这样子滴:首先进行类型检查,检查类型不同,报错!如果类型相同,再进行类型擦除啦!!!(即进入擦除阶段,需要通过检查那一关)