泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
Java语言引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的情况下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显示的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器不提示错误,在运行的时候才会出现异常,这是一个安全隐患。隐患示例如下:
import java.util.*;
public class Test25_1 {
public static void main(String[] args) {
ArrayList al = new ArrayList();
// 创建一只狗,并存放到集合中
Dog dog1 = new Dog("旺财", 2);
al.add(dog1);
//从集合中取出
Dog temp1 = (Dog)al.get(0); //此处一定需要作强制转换,否则编译报错
Cat temp2 = (Cat)al.get(0); //此处编译不会报错,但是运行时会报类型转换错误
}
}
class Dog
{
private String name;
private int age;
public Dog(String name, int age)
{
this.name = name;
this.age = age;
}
}
class Cat
{
private String name;
private String color;
public Cat(String name, String color)
{
this.name = name;
this.color = color;
}
}
上述代码运行,会报类型转换错误:
泛型的好处是在编译的时候检测类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。如下,改成下面的代码,便不需要作强制转换。
public static void main(String[] args) {
ArrayList<Dog> al = new ArrayList<Dog>(); //使用泛型
// 创建一只狗,并存放到集合中
Dog dog1 = new Dog("旺财", 2);
al.add(dog1);
//从集合中取出
Dog temp1 = al.get(0); //无需强制转换
Cat temp2 = al.get(0); //编译报错
}
通过泛型反射机制,可以获得类的很多信息,比如类的名称、类的函数名称、函数的返回类型等。
import java.util.*;
import java.lang.reflect.*;
public class Test25_1 {
public static void main(String[] args) {
Gen<Integer> gen1 = new Gen<Integer>(1);
gen1.showTypeName();
Gen<String> gen2 = new Gen<String>("apple");
gen2.showTypeName();
Gen<Bird> gen3 = new Gen<Bird>(new Bird());
gen3.showTypeName();
gen3.showMethodName();
}
}
//定义一个泛型类
class Gen<T>
{
private T o;
// 构造函数
public Gen(T t)
{
o = t;
}
// 通过反射机制,得到T类型的名称
public void showTypeName()
{
System.out.println("类型是:"+o.getClass().getName());
}
// 通过反射机制,得到T类型的成员函数名称
public void showMethodName()
{
Method[] m = o.getClass().getDeclaredMethods();
for (int i = 0; i<m.length; i++)
{
System.out.println("函数名是:"+m[i].getName());
}
}
}
class Bird{
public void test1()
{
System.out.println("Bird class");
}
public void count(int a, int b)
{
System.out.println(a+b);
}
}
运行结果: