泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。
在前面几篇介绍集合框架的博客中,我们已经使用了泛型,在这一篇博客中,详细的为大家介绍一下泛型的使用。
在没有泛型之前,我们使用集合是这样写的,以ArrayList为例。
import java.util.ArrayList;
public class GenericsDemo
{
public static void main(String[] args)
{
ArrayList list = new ArrayList();
// 向集合中添加字符串
list.add("jiang");
// 向集合中添加整型数据
list.add(1);
// 向集合中添加布尔型数据
list.add(true);
System.out.println(list);
}
}
上面的例子我么可以看到,在不使用泛型的时候,我们可以向集合中添加任意类型的数据(基本数据类型会自动装箱成对象),这样就会出现一个问题,在使用集合的时候,我们不知道集合元素的类型,很容易出现错误,使用泛型之后,我们就可以限制集合中元素的数据类型,方便我们对其操作。
通过截图我们可以看到,在使用泛型后,我们再向集合中添加与泛型不匹配的数据时,就会编译出错。
在使用泛型的时候,有如下规则限制:
- 泛型的类型参数只能是类类型(包括自定义类),不能是简单类型。
- 同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
- 泛型的类型参数可以有多个。
- 泛型的参数类型可以使用extends语句,例如。习惯上称为“有界类型”。
- 泛型的参数类型还可以是通配符类型。例如Class
在类上使用泛型
集合中的泛型是JAVA中写好的,我们也可以编写自己的类并使用泛型,举个例子:
/**
* 自定义类,使用泛型
*
* @author jianggujin
*
*/
public class Generics<T>
{
T obj;
public Generics(T obj)
{
this.obj = obj;
}
public T getObj()
{
return obj;
}
public static void main(String[] args)
{
Generics<String> generics = new Generics<String>("jianggujin");
System.out.println(generics.getObj());
}
}
上面的例子只是简单的演示了一下在类中如何使用泛型,如果我们需要多个泛型参数时,我们只需要这样写:
public class Generics<K, V>
{
//...
}
我们还可以添加更多的反省参数列表,只需要使用,
隔开。
在方法上使用泛型
泛型不仅可以用在类上,还可以在方法上使用泛型,假设我们有一个方法,作用是把一种数据类型的数据强制转化为指定数据类型的数据,我们可以这样写:
import java.util.ArrayList;
import java.util.List;
public class Generics
{
// 为了方便直接使用静态方法
public static <T> T convert(Class<T> clazz, Object obj)
{
return (T) obj;
}
public static void main(String[] args)
{
List list = new ArrayList();
ArrayList conObj = convert(ArrayList.class, list);
}
}
例子只是起到演示的效果,实际应用中不会这么去使用。在上面的例子中,我们只需要关心如何在方法上使用泛型,所以我们只需要关心convert
方法的定义。