来自《java编程思想》的定义,泛型实现了参数化类型的概念,使代码可以应用于多种类型。“泛型”这个术语的意思是:“适用于许多许多的类型”。泛型在编程语言中出现时,其最初的目的是希望类或方法能够具备最广泛的表达能力。如何做到这一点呢,正是通过解耦类或方法与所使用的类型之间的约束。java引入泛型的一个很大用于就是java的容器类,容器就是存放对象的地方,事实上,所有的程序在运行时都要求你持有一大堆对象,所以,容器算得上最具重用性的类库之一。
看一下下面这个类,这个类只能持有一种对象Automobile。没有问题,但是当需要持有多种对象时,代码的可重用性就比较差了。
class Automobile {}
class Test1 {
private Automobile a;
public Test1(Automobile a) {
this.a = a;
}
Automobile get() {
return a;
}
}
为了持有多种对象,在Java SE5之前,我们可以让一下这样的类持有Object类型的对象,一次提高代码的重用性。从下面代码可以看到,Test2类明显可以比Test1类持有很多对象,而且代码可重用性做的比较好。
package com.zy.test;
public class Holder1 {
public static void main(String[] args) {
Test2 t2 = new Test2(new Automobile());
Automobile a = (Automobile)t2.getA();
t2.setA("not a Automobile");
String s = (String)t2.getA();
}
}
class Automobile {}
class Test2 {
private Object a;
public Test2(Object a) {
this.setA(a);
}
public Object getA() {
return a;
}
public void setA(Object a) {
this.a = a;
}
}
有些时候,我们确实希望容器能够容器能够持有多种类型的对象,但是,通常而言,我们只会使用容器来存储一种类型的对象。泛型的主要目的之一就是用来指定容器要持有什么类型的对象,而且由编译器来保证类型的正确性。因此,与其使用Object,我们更喜欢暂时不指定类型,而是稍后再决定具体使用什么类型。要达到这个目的,需要使用类型参数,用尖括号括住,放在类名后面。然后使用这个类的时候,再使用实际的类型替换此类型参数,下面的例子中T就是类型参数:
package com.zy.test;
public class Holder1 {
public static void main(String[] args) {
Test3<Automobile> t3 = new Test3<Automobile>(new Automobile());
Automobile b = t3.getA();
}
}
class Test3<T> {
private T a;
public Test3(T a) {
this.setA(a);
}
public T getA() {
return a;
}
public void setA(T a) {
this.a = a;
}
}
上面的例子中,当你创建Test3对象时,必须指明持有什么类型的对象,将其至于尖括号内。然后,你就能在Test3中存入该类型对象,并且在取出时取出他持有的对象(自动,正确)。其实这就是泛型的核心概念:告诉编译器想使用什么类型,然后编译器帮你处理一切细节。你可以认为泛型与其他类型是差不多的。