什么是泛型?
泛型,即“参数化类型”。它的本质是为了将类型参数化, 也就是说在泛型使用过程中,数据类型被设置为一个参数,在使用时再从外部传入一个数据类型;而一旦传入了具体的数据类型后,传入变量(实参)的数据类型如果不匹配,编译器就会直接报错。这种参数化类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
通俗讲,泛型:
就是适用于许多许多类型
。从代码上讲,就是对类型实现了参数化。
语法
class
泛型类名称
<
类型形参列表
>
{
//
这里可以使用类型参数
}
class
ClassName
<
T1
,
T2
, ...,
Tn
>
{
}
class
泛型类名称
<
类型形参列表
>
extends
继承类
/*
这里可以使用类型参数
*/
{
//
这里可以使用类型参数
}
class
ClassName
<
T1
,
T2
, ...,
Tn
>
extends
ParentClass
<
T1
>
{
//
可以只使用部分类型参数
}
class Arrays{
public Object[] objects = new Object[10];
public Object getPos(int Pos){
return objects[Pos];
}
public void setVal(int Pos, Object val){
objects[Pos] = val;
}
}
public class Demo {
public static void main(String[] args) {
Arrays Array = new Arrays();
Array.setVal(1,100);
Array.setVal(2,"Hello");
String a = Array.getPos(2);
System.out.println(a);
}
}
运行后,我们会发现它会报错,如图所示:
这是因为虽然我们的Arrays类型数组是Object[]类型的,但是当我们对它进行存储String类型数值时候,在读取它的数值我们得到的是一个Object类型的数据,而我们此时要做的要么将他变成
String a = (String)Array.getPos(2);
Object a = Array.getPos(2);
这两种都可以使得不报错,但是对个人而言更喜欢第一种。
类型擦除
泛型的本质是将数据类型参数化,它通过擦除的方式来实现,即编译器会在编译期间擦除代码中的所有泛型语法并相应的做出一些类型转换动作。
换而言之,泛型信息只存在于代码编译阶段,在代码编译结束后,与泛型相关的信息会被擦除掉,专业术语叫做类型擦除。也就是说,成功编译过后的 class 文件中不包含任何泛型信息,泛型信息不会进入到运行时阶段
。
实例:
还是如上图所示的代码,我们在用cmd对该文件进行javap -c后, 通过查看它的字节码文件我们可以得到,所有的T都是Object。
在编译的过程当中,将所有的
T
替换为
Object
这种机制,我们称为:
擦除机制
。
Java
的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息。