泛型技术在C#和Java之中的使用方式看似相同,但实现上却有着根本性的分歧,C#里面泛型无论在程序源码中、编译后的IL中(Intermediate Language,中间语言,这时候泛型是一个占位符)或是运行期的CLR中都是切实存在的,List<int>与List<String>就是两个不同的类型,它们在系统运行期生成,有自己的虚方法表和类型数据,这种实现称为类型膨胀,基于这种方法实现的泛型被称为真实泛型。
Java语言中的泛型则不一样,它只在程序源码中存在,在编译后的字节码文件中,就已经被替换为原来的原始类型(Raw Type,也称为裸类型)了,并且在相应的地方插入了强制转型代码,因此对于运行期的Java语言来说,ArrayList<int>与ArrayList<String>就是同一个类。所以说泛型技术实际上是Java语言的一颗语法糖,Java语言中的泛型实现方法称为类型擦除,基于这种方法实现的泛型被称为伪泛型。(类型擦除在后面在学习)
使用泛型机制编写的程序代码要比那些杂乱的使用Object变量,然后再进行强制类型转换的代码具有更好的安全性和可读性。泛型对于集合类来说尤其有用。
在使用泛型之前,先了解下泛型的几个基本概念,以ArrayList<E>和ArrayList<Integer>做简要介绍:
整个成为ArrayList<E>泛型类型
ArrayList<E>中的 E称为类型变量或者类型参数
整个ArrayList<Integer> 称为参数化的类型
ArrayList<Integer>中的integer称为类型参数的实例或者实际类型参数
·ArrayList<Integer>中的<Integer>念为typeof Integer
ArrayList称为原始类型
泛型的使用
泛型有以下三种,分别是泛型类、泛型接口和泛型方法
1.泛型类
1.1简单泛型类的使用
泛型类就是具有一个或多个类型变量的类,泛型类是在多个方法签名间实施类型约束。在 List<V> 中,类型参数 V 出现在 get()、add()、contains() 等方法的签名中。当创建一个 Map<K, V> 类型的变量时,您就在方法之间宣称一个类型约束。您传递给 add() 的值将与 get() 返回的值的类型相同。泛型类的使用很简单,如下
class Pair<T> {
private T value;
public Pair(T value) {
this.value=value;
}
public T getValue() {
return value;
}
public void setValue(T value) {
this.value = value;
}
}
使用的时候我们可以这样定义Pair<String> pair=new Pair<String>("Hello");
Pair类引入了一个类型变量T,用尖括号<>括起来,并放在类名的后面。泛型类可以有多个类型变量。例如,可以定义Pair类,其中第一个域和第二个域使用不同的类型:public class Pair<T,U>{......}
1.2泛型返回类型的方法
下面的代码列举了使用一个在普通类ArrayAlg中返回类型为泛型的方法minmax,用其来获取字符串数组words中的字符串字典排序。
class ArrayAlg
{
public static Pair<String> minmax(String[] a)
{
if (a == null || a.length == 0) return null;
String min = a[0];
String max = a[0];
for (int i = 1; i < a.length; i++)
{
if (min.compareTo(a[i]) > 0) min = a[i];
if (max.compareTo(a[i]) < 0) max = a[i];
}
return new Pair<String>(min, max);
}
}
2.泛型接口
interface Show<T,U>{
void show(T t,U u);
}
class ShowTest implements Show<String,Date>{
@Override
public void show(String str,Date date) {
System.out.println(str);
System.out.println(date);
}
}
3.泛型方法
泛型方法是因为您想要在该方法的多个参数之间宣称一个类型约束。如下:
3.1普通类中的泛型方法
public class Pair
{
public static <T> T getMiddle(T[] b) {
return b[b.length/2];
}
}
这个方法是用在普通类中定义的,而不是用在泛型类中定义。但是,这是一个泛型方法,这一点可以从尖括号和类型变量中看出来。 需要注意的是,类型变量放在修饰符的后面,返回类型的前面。当然泛型方法可以定义在普通类中,也可以定义在泛型类中。
泛型方法的调用
String[] names = { "mmj", "geeeeg.", "sa" };
String middle = ArrayAlg.<String>getMiddle(names);
在这种情况下,方法调用中可以省略掉<String>类型参数。编译器有足够的信息来判断出多调用的方法。它用的names的类型(即String[ ]类型)与泛型类型T[ ]进行匹配,并且判断出T一定是String。也就是说String middle = ArrayAlg.getMiddle(names)也是对的
3.2泛型类中的泛型方法
public class Pair<T>
{
public Pair() { first = null; second = null; }
public Pair(T middle){ this.middle = middle;}
//泛型方法
public T getSth1<T>(T t)
{
return t;
}
public void getSth2<T>(T t)
{
}
//非泛型方法
public T getMiddle(){return middle;}
private T middle;
public T length; //length要用public或者默认访问修饰符
}
3.3泛型返回类型的泛型方法
class ArrayAlg
{
public static <T> Pair<T> getMiddle(T[] b) //这里的泛型方法返回类型为Pair<String>
{
return new Pair<T>(b[b.length / 2]); //b[b.length / 2]是T[]类型,所以无需强制类型转换。
}
}
调用如下String[] names = { "mmj", "geeeeg.", "sa" };
Pair<String> middle = ArrayAlg.<String>getMiddle(names);
//如前所述Pair<String> middle = ArrayAlg.getMiddle(names);也可以。
参考:
1.http://blog.csdn.net/zzy7075/article/details/50467089##3