Java -- Java泛型机制简述(一)

Java -- Java泛型机制简述(一)


一、概要

泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。 Java语言引入泛型的好处是安全简单。
在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,以提高代码的重用率。

 

二、泛型类

一个泛型类,就是具有一个或多个类型变量的类。在定义泛型类时,要将类型变量用尖括号(<>)括起来,并放在类名的后面:

/**
 * Generic class with limited type variable
 * 
 * @author xzm
 *
 * @param 
 */
class Employee & Serializable> {

	T employeeA;
	T employeeB;

	public Employee(T employeeA, T employeeB) {
		super();
		this.employeeA = employeeA;
		this.employeeB = employeeB;
	}

	public T getEmployeeA() {
		return employeeA;
	}

	public void setEmployeeA(T employeeA) {
		this.employeeA = employeeA;
	}

	public T getEmployeeB() {
		return employeeB;
	}

	public void setEmployeeB(T employeeB) {
		this.employeeB = employeeB;
	}

}

/**
 * Generic class without limited type variable
 * 
 * @author xzm
 * @param 
 *            Generic type
 */
class Pair {

	private T first;
	private T second;

	public Pair() {
		first = null;
		second = null;
	}

	public Pair(T f, T s) {
		first = f;
		second = s;
	}

	public T getFirst() {
		return first;
	}

	public void setFirst(T first) {
		this.first = first;
	}

	public T getSecond() {
		return second;
	}

	public void setSecond(T second) {
		this.second = second;
	}
}

Pair和Employee类引入了一个类型变量"T"。如果我们要使用多个类型变量,只需要在<>尖括号中添加,同时各个类型变量之间以","隔开。在使用泛型类时,我们要指定一个明确的类型来初始化泛型类。Java中的集合框架基本都使用了泛型。例如,当我们要使用ArrayList存储String对象时,我们通常会这样进行初始化:

		List list = new ArrayList();
		list.add("aaa");

泛型在编译期间会提供类型检查,例如往list中添加Integer对象,将会报一个编译错误。这无疑提供了代码的安全性。

Java SE中,ArrayList是这样声明的:

public class ArrayList extends AbstractList
        implements List, RandomAccess, Cloneable, java.io.Serializable

它使用了类型变量E,我们在初始化ArrayList时,给它指定一个明确的类型:String。同理,我们使用Pair类:

Pair pair = new Pair();

当我们给某个泛型类指定特定类型时,从代码来说,它有很好的可读性,因为应用于泛型类的类型显而易见。

在Java SE7及以后的版本中,构造函数中可以省略泛型类型。同样的Pair定义,我们可以这样:

		Pair pair = new Pair<>();

省略的类型,编译器可以很简单地从变量的类型推断得出。两种写法都符合要求,我们可以自由选择。

 

三、泛型方法

泛型方法既可以出现在非泛型类中,也可以出现在泛型类中。下面我们在非泛型类中进行介绍。看如下的一个示例:

class GenericMethod {

	/**
	 * 
	 * @param param1
	 *            generic type
	 * @param param2
	 *            generic type
	 * @return
	 */
	public static  String genericMethod(T param1, U param2) {
		return "param1: " + param1.toString() + " param2: " + param2.toString();

	}
}

在GenericMethod类中,我们定义了一个泛型方法genericMethod(),它使用了两个类型变量:T和U,返回值为String。尖括号包裹的类型变量:"",表明这是一个泛型方法。在泛型方法中,类型变量要放在修饰符的后面,返回值类型的前面。

泛型方法的使用,跟泛型类基本一致,提供具体的类型即可:

		GenericMethod.genericMethod(1.3, 2);

泛型中, 类型变量只代表某种引用类型,不包括基本数据类型。此例中,可以传入基本类型变量是因为现在Java提供了自动拆装箱机制,1.3和2会自动地被转换为对应的包装类型对象。当然,泛型方法的返回值也可为类型变量类型。

 

四、泛型接口

泛型接口的情形跟泛型类是基本类似的,就不在多做介绍,我们只举一个示例,我们经常使用的Comparable接口定义:

public interface Comparable {
   
    public int compareTo(T o);
}

 

以上主要介绍了泛型的一些基本定义和使用方法。要很好地理解泛型,我们还必须了解泛型中的"类型擦除",这一部分将在第二篇中再作介绍。

你可能感兴趣的:(编程开发杂类)