1. 概述
泛型在java中有很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用。
什么是泛型?为什么要使用泛型?
泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)。
泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型)。也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法。
为什么要使用泛型?我们来看一个例子:
上面程序在编译时没有任何问题,但是当运行时肯定会报错,如下图所示:
由于ArrayList中可以存放任意类型,所以上面例子中add String和Integer类型不会有任何问题,但是在使用时把arrayList中的数据全当作String类型来用,肯定会有问题。为了解决这个问题,使程序正常运行我们需要进行类型判断。如下面所示:
这样程序可以正常运行了,但是可以看出这样用起来比较麻烦,因为我们就只是想在arrayList中存放String类型,但是由于各种原因arrayList中可能被添加非String类型,在操作arrayList中的数据时,我们一是需要我们进行类型判断,二是需要进行强制类型转换。
那有没有办法只允许arrayList中只能添加String类型,添加其他类型在编译时就直接报错,然后使用arrayList中的元素时,直接当成String类型使用,而不需要进行类型判断以及强制类型转换呢?这时泛型就应运而生了。我们用泛型改造一下上面的例子:
使用泛型后,如果添加非String类型数据时,编译时直接会报错,如果用eclipse、intellij idea等IDE开发工具编写程序的话,添加非String类型数据时直接会提示错误,如下:
2.泛型的使用
泛型有三种使用方式,分别为:泛型类、泛型接口、泛型方法。
泛型类
泛型类型用于类的定义中,被称为泛型类。通过泛型可以完成对一组类的操作对外开放相同的接口。最典型的就是各种容器类,如:ArrayList、HashSet、HashMap。
泛型类的定义如下:
下面是一个常见的泛型类使用方法:
那么问题来了,定义的泛型类,在实例化对象时就一定要传入泛型类型实参么?并不是这样,在使用泛型的时候如果传入泛型实参,则会根据传入的泛型实参做相应的限制,此时泛型才会起到本应起到的限制作用。如果不传入泛型类型实参的话,在泛型类中使用泛型的方法或成员变量定义的类型可以为任何的类型。比如List、Map等集合类型。
看下面的例子:
注意:
1:泛型的类型参数只能是类类型,不能是普通的基本类型。
2:不能对确切的泛型类型使用instanceof操作,如下面的操作是非法的,编译时就会报错:
泛型接口
泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中,可以看一个例子: