从c++开始,就有泛型概念的讲解了,本回中,我们将谈论一些关于Java的泛型问题。
简单说,泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用。我们拿ArrayList来举例,在泛型出现之前,ArrayList类只维护一个Object引用的数组。这样子就有两个问题,当获取一个值的时候,必须进行强制转换。
ArrayList files = new ArrayList();
...
String filename = (String)files.get(0);
此外,这里没有检查错误。可以向数组列表添加任何类的对象。
files.add(new File("..."));
对于这个调用,编译和运行都不会出错,然而在其他地方,如果将get的结果强制类型转换为String类型,就会产生一个错误。
对此,泛型就能提供一个优秀的解决方案:类型参数。ArrayList类有一个类型参数用来指示元素的类型:ArrayList<String>files = new ArrayList()
省略的类型可以从变量的类型中推断出来,这样对编译器也很舒服,当调用get的时候,不用进行强制类型转换,编译器就知道返回值类型为String类型,而不是Object。
这就是泛型的优势,泛型程序设计分为三个能力级别:基本级别是,仅仅使用泛型类——典型的是像ArrayList这样的集合——不必考虑他们的工作方式与原因。但是我们也可以实现自己的泛型类,以及泛型方法。
Q1:如何定义简单地泛型类
一个泛型类,就是具有一个或多个类型变量的类。举个例子,关于Pair:
public class Pair<T>
{
private T first;
private T second;
public Pair(){first = null;second = null;}
public Pair(T first,T second){this.first=first...}
public getFirst(){retrurn first;}
...
public void setFirst(T newValue){first = newValue;}
public void serSecond(T newValue){second = newValue;}
}
Pair类引入了一个类型变量T,放在类名后面。泛型类可以有多个类型变量,看下面:
public calss Pair(T,U){
...
}
Q2:既然都都定义了一个泛型类了,那如何定义类中的一个泛型方法呢?
直接看例子:
class ArrayAlg
{
public static <T>T getMiddle(T...a)
{
return a[a.length / 2];
}
}
泛型方法可以定义在普通类中,也可以定在泛型类中。
可以调用时,可以在方法名前的尖括号中放入具体类型:
String middle = Arraylg.<String>getMiddle("John","Q.","public");
但是在实际中的大多数情况下,方法调用中可以省略,因为编译器能从参数中推断出所调用的方法一定是什么类型。
也就是说,可以这样String middle = Arraylg.getMiddle("John","Q.","Public");
Q:我们用一个例子来说明这个问题:
class Arraylg
{
public static <T> T min(T[] a)
{
if(a == null || a.length == 0) return null;
T smallest = a[0];
for(int i = 1;i<a.length;i++)
if(smallest.compateTo(a[i])>0) smallest = a[i];
return smallest;
}
}
这里就存在一个问题,在min方法中,我们samllest的类型为T,意味着他可以是任何一个对象,但是这个方法中使用了compareTo方法,我们无法保证T所属的类有compareTo方法!解决这个问题,我们可以通过对T的限制来完成.
像这样,public static <T extends Comparable>T min(T[] a)
…
这样子的话,min方法就只能被实现了Comparable接口的类的数组调用了