泛型初识
为什么需要泛型?
在Java没有泛型之前,类似于ArrayList
这种为所有类提供相同功能的工具类为了保证泛用性,都是采用Object
作为存储数据的类别。
在JDK1.5版本前,ArrayList
等集合框架内部都有一个Object
类型数组,通过这样的手段,集合框架就成了一个能持有多种对象的通用工具。
public class ArrayList {
private Object[] array;
private int size;
public void add(Object e) {...}
public void remove(int index) {...}
public Object get(int index) {...}
}
这样就可以使用上述Arraylist
存储String
、User
等数据类型,但是这样存储有几个缺点:
- 需要强制转型
- 类型控制困难,使用不方便,易出错
ArrayList list = new ArrayList();
// 假如先存储了hello字符串到list中,在list中被转成Object
list.add("hello world");
String str = (String) list.get(0);
因为在list
中是按照Object
存储的,所以在使用get()
方法取出来时必须强转为String
。
同样的,因为是使用Object
类型来存储的,因此所以类型的数据都可以通过add()
方法放入list
。
像下面这样使用add()
方法,将Integer
存入list
时,不会产生错误。
list.add(new Integer(3123123));
String str2 = (String) list.get(1);
但是在使用get()
方法获取到Integer
对象,并且将其强转为String
时,就会出现类型强转错误。
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
要解决这个问题,除非针对每一种类型都创建一个专属的ArrayList
:
public class ArrayList {
private String[] array;
private int size;
public void add(String e) {...}
public void remove(int index) {...}
public String get(int index) {...}
}
但是这样的话,有多少类就需要多少创建多少个专属的ArrayList
,实在是难以实现。
泛型
为了解决上述问题,在JDK1.5中,Java添加了泛型这一特性,有了泛型之后,ArrayList
的代码就变为:
public class ArrayList {
private T[] array;
private int size;
public void add(T e) {...}
public void remove(int index) {...}
public T get(int index) {...}
}
代码中的T
可以是任意一种类型。任何一种类型都可以使用这个模板,比如String
,
ArrayList arrayList = new ArrayList<>();
使用泛型有一个更大的好处。在没有泛型前,使用Object类可以保存任意类,程序的错误只有在运行期才能检测出来。而使用了泛型后,像下面的代码中想要存入其他类型的数据时,编译阶段就会报错。
// 编译阶段就直接报错,
arrayList.add(new Integer(12344141));