一.什么是泛型
泛型,即“参数化类型”,顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)
泛型可应用于:类,接口,方法, 称作泛型类,泛型接口,泛型方法
泛型的用处:统一指定泛型类,接口,方法中操作的数据类型,提高泛型类,接口,方法的适用性
看不懂没关系,继续往下看即可
二.泛型类,泛型接口,泛型方法
1).泛型类(以ArrayList类为例)
首先是ArrayList类的声明语句:
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {...}
(注意 : 上边声明语句内,所有的<E>都代表同一种数据类型(同一个<E>),详情请查询泛型的继承)
1.泛型<E>就是用于指定ArrayList类中操作的数据类型,<E>可以用于指定任何类型,
如果要使用泛型,那么类实例化时,就必须声明类的泛型类型,如下:
List<String> StrList = new ArrayList<String>();
<String>就是<E>的值,表示StrList对象操作的数据类型为String类型,
如果不想使用泛型,不定义泛型类型即可,如下:
List list = new ArrayList();
接着我们看一下ArrayList类中定义的一些方法:
public E get(int index) {...} public E set(int index, E element) {...}
2.标记符E表示某种数据类型,类名后的<E>指定为什么类型,类中的标记符E就代表什么类型
比如我们刚才声明的泛型为<String>的变量StrList调用这两个方法:
String name = StrList.get(3); StrList.set(3, "My name is ...");
泛型接口和泛型类用法相似,不赘述
2).泛型方法(以ArrayList类中的方法为例)
首先找一个ArrayList类中的泛型方法:
public <T> T[] toArray(T[] a) {...}
该方法可以用于把ArrayList对象中的数据,导入到T[]数组a中,并返回该数组
1.泛型声明在权限标识符后,返回类型前
声明后方法中就可以用标记符T来表示操作的数据类型了.实例如下
String[] StrArray = StrList.toArray(new String[10]);
泛型中的标记符的含义:
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的java类型
S、U、V - 2nd、3rd、4th types
也可以自定义泛型标记符,只要是大写字母即可.
三.泛型擦除
在代码编译的过程中,泛型会被JVM擦除,比如
List<String>,擦除泛型后会变成List.
为什么这样做呢?
1.避免大改JVM,如果保留泛型到运行期,那么将大大增加JVM的工作量
2.兼容旧代码
泛型只有在代码检查阶段起作用!
四.泛型的通配符和上下边界
1).泛型通配符<?>
泛型通配符<?>表示可以传入任何类型的类型参数,在不能确定类型的时候使用<?>
2).和其他标记符(比如<E>, <T>)的区别
<?>不能在声明泛型类,泛型接口,泛型方法时使用,否则会报错,语法错误.
<?>主要用于设定参数类型的泛型时使用,可以代指任何泛型(比如<E>, <T>等)比如:
public void sort(Comparator<? super E> c) {...}
<? super E>就是用来指定Comparator类的泛型,表示所有E类型的父类.
3).泛型的上下边界
泛型在声明时,可以指定泛型的上下边界,比如:
public void sort(Comparator<? super E> c) {...} public boolean addAll(int index, Collection<? extends E> c) {...}
关键字super在泛型中表示下边界,extends表示上边界
举例说明
<? super E> : 所有E类的父类(包括E)
<? extends E> : 所有E类的子类(包括E)