一,泛型概述

​ 关于泛型,先来说几句集合。都知道集合是可以存储任意对象,当我们创建一个集合时如果没有声明它的存储类型,那该集合便自动提升为Object类型。请参看如下代码:

public class GenericDemo { 	public static void main(String[] args) { 		Collection coll = new ArrayList(); 		coll.add("abc"); 		coll.add("hello"); 		coll.add(5);//由于集合没有做任何限定,任何类型都可以给其中存放         // 使用迭代器遍历集合 		Iterator it = coll.iterator(); 		while(it.hasNext()){ 	//需要打印每个字符串的长度,就要把迭代出来的对象转成String类型 			String str = (String) it.next(); 			System.out.println(str.length()); 		} 	} } 

​ 毫无疑问,以上代码会报错,首先从代码上看在集合中存储了数值类型,字符串类型。但是在使用迭代器遍历时,取出的是String类型的,那么对于数值类型来说就必然会报错。 

​ 那么以上问题该怎么解决呢?通常对于Collection集合来说,同一个集合对象只保存一种数据类型。如下代码所示:

 		// 存储字符类型         Collection<String> stringCollection = new ArrayList<>();         // 存储数值类型         Collection<Integer> integerCollection = new ArrayList<>();         // 存储精度类型         Collection<Double> doubleCollection = new ArrayList<>(); 

​ 也就是说在我们初始化集合的时候,就已经将存储存储类型固定。但是按照Java的灵活性来说,这是显然不够的,比如预先并不确定要存储的类型。因此在JDK5之后新增了泛型的语法,使我们的程序显得更为灵活。

泛型:在方法或者类(接口)中预先的使用某种未知的数据类型。

​ **提示:**在我们创建对象的时候,如果没有明确指出一种数据类型,那么编译器会默认为Object类。

1.1,泛型的意义

​ 那说了这么多,泛型又能解决什么问题呢?针对上面的案例分析:

​ 1,可以将ClassCastException异常由运行期转到编译期异常。

​ 2,避免强制类型的转换。

​ 请看如上代码,在我们初始化集合时指定String数据类型,此时再存储数值类型就会在编译期报错,那么泛型又将如何运用呢。先别急,我们先看看集合中是如何定义的。 

​ 在Array List集合源码中看出,它的存储类型是一个E,这是什么呢?

  • E,Elements:元素
  • T,Type:类型

​ 这就是泛型,因为我们对于集合来说它们并不知道我们要存储是什么类型,因此这就是泛型的意义。

​ **提示:**泛型是数据类型的一部分,我们将类名与泛型合并一起看做数据类型。

​ 泛型,用来灵活地将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递。

二,泛型类

​ 编写格式:

修饰符 class 类名称<泛型变量>{} 

​ 我们还是以集合为例,请看如下集合源代码实现,以add方法作为参考。

​ 可以看出add方法接收的数据类型为E,与我们上一节图片中所示Array List源码实现是一致的,因为Array List接收的参数类型就是E。说这么多有些啰嗦,现在先定义一个泛型类。

public class GenericClass<T> {     private T key;    public void setKey(T key){        this.key = key;    }    public T getKey(){        return key;    } } 
public class GenericDemo {     public static void main(String[] args) {         GenericClass<String> genericString =