目录
在ArrayList类中,我们发现有个<E>的存在,我们知道它叫泛型。
准确的说,ArrayList是一个泛型类,具有一个泛型类型E。(E代表的就是元素)
泛型的意义在于我们可以编写参数化的类型。
(一)没有泛型
1、概述
我们知道所有java类都衍生自java.lang.Object,也就是说所有对象都可以转换为Object类。那么意味着一个集合可以接受任意类型的参数,那么当我们需要从集合中取出某个元素的时候,我们并不会得知该元素是什么类型(因为只是单单存储了某个元素并没有存储该元素的类型),那么想对该元素进行后续操作时则非常不便(我们往往需要借助转型操作)。
2、总结(泛型的优点)
1、在编译时指出错误,而不是等到运行时指出错误
2、避免了强制类型的转换
(二)泛型基础知识
<1>、定义
1、概念
泛型,是JDK5中引入的特性,其本质是参数化类型。
(参数:定义方法时有形参,调用此方法时传递实参。而参数化类型则是:将原来的具体的类型参数化,在使用/调用时传入具体的类型)
2、使用范围
泛型(参数化类型)可以用在类、方法、接口中(分别被称为 泛型类、泛型方法、泛型接口)
<2>、泛型定义格式
<类型>:指定一种类型的格式
<类型1,类型2···>:指定多种类型的格式
1、泛型类
格式:修饰符 class 类名 <类型>{ }
eg. publlic class MyList<T>{ }\
2、泛型方法
格式:修饰符 <类型> 返回值类型 方法名(类型 变量名){ }
eg. public <T> void show(T t){ }
3、泛型接口
格式:修饰符 interface 接口名<类型>{ }
eg. public interface ButtonInterface<T>{ }
<3>、类型通配符
1、类型通配符
表示方式:<?>
2、定义
List<?>表示的是元素类型未知的List,其元素可以是任何的类型。这种通配符仅仅表示List的父类或子类,并不能向其中添加元素。
我们还能看见一些T、E、K、V等字母。当然我们可以用任何字母,但是最好有一定的含义,具体如下:
T(type):表示具体的一个java类型
E(element):代表元素
K(key),V(value)
3、通配符上限
格式:<? extends 类型>
eg. List<? extends Number> (表示的类型是Number或其子类型)
//Object为Number父类
//Number为Integer父类
//通配符上限
List<? extends Number> List1 = new ArrayList<Obiect>();
//报错,因为,Obiect为其父类,超过了最大上限Number
List<? extends Number> List1 = new ArrayList<Number>();
//成功,未超过最大上限
List<? extends Number> List1 = new ArrayList<Integer>();
//成功,未超过最大上限
4、通配符下限
格式:<类型 extends ?>
eg. List<Number extends ?> (表示的类型是Number或其父类型)
<4>、集合中的泛型(包装类型)
集合类的泛型是不允许使用基本数据类型(泛型参数必须是一个类,即Object 类的子类,int属于原始数据类型,并不是一个类,所以无法使用与java泛型中),因此当我们使用int类型时,需要用integer进行代替。
八大数据类型如下(基本数据类型所对应的包装类型):
基本数据类型 | 包装类型 | |
整数类型 | byte | Byte |
short | Short | |
int | Integer | |
long | Long | |
浮点类型 | float | Float |
double | Double | |
字符型 | char | Character |
布尔型 | boolean | Boolean |
<5>、泛型如何编译
泛型所利用的机制是擦除机制。在使用泛型时若没有指明数据类型,那么就会擦除泛型类型。
在虚拟机中是没有泛型的,编译器会使用类型擦除来处理泛型,使其变成普通类。当我们定义了一个泛型类型,在擦除后都会变成原始类型(去掉类型参数后的泛型类型名,类型变量擦除后被替换为其限定类型,对于没有限定的变量则替换为Object类型),在必要时使用强制类型转换,使虚拟机识别。
<6>、静态方法中的泛型
在静态方法中也可以使用泛型,但是必须将静态方法定义为泛型方法