href="file:///C:%5CDOCUME%7E1%5Cothers%5CLOCALS%7E1%5CTemp%5Cmsohtml1%5C01%5Cclip_filelist.xml" rel="File-List" />
Java 泛型编程
简单泛型类
代码:
public class MyData<T> {
private T data1;
private T data2;
/**
* @return the data1
*/
public T getData1() {
return data1;
}
/**
* @param data1 the data1 to set
*/
public void setData1(T data1) {
this.data1 = data1;
}
/**
* @return the data2
*/
public T getData2() {
return data2;
}
/**
* @param data2 the data2 to set
*/
public void setData2(T data2) {
this.data2 = data2;
}
public void printData() {
System.out.println("data1 :" + this.data1 + "/n"
+"data2 :" + this.data2);
}
public static void main(String args[]) {
//建立一个String类型的数据进行测试
MyData<String> data = new MyData<String>();
data.setData1("data1");
data.setData2("data2");
data.printData();
}
}
2. 泛型方法
可以定义在普通类或泛型类中。
如代码:
//泛型方法
public static <T> T getInfo(T info) {
return info;
}
或
//泛型方法2
public static <T> void getInfo(T info) {
return info;
}
调用方法:可以直接像普通方法一样进行调用。
3.类型变量的限定
对类变量类型进行限定,比如,类变量必须实现Comparable结口,则类变量的可以这样进行约束:T extends Comparable。如对上面代码可以这样写:
public static <T extends Comparable> T getInfo(T info) {
return info;
}
如果T有多个可选类的话刚可以写为:T extends Comparable & Class2 & Class3….
4.类型擦除
因为泛型其实只是在编译器中实现的而虚拟机并不认识泛型类项,所以要在虚拟机中将泛型类型进行擦除。也就是说,在编译阶段使用泛型,运行阶段取消泛型,即擦除。
擦除是将泛型类型以其父类代替,如String 变成了Object等。其实在使用的时候还是进行带强制类型的转化,只不过这是比较安全的转换,因为在编译阶段已经确保了数据的一致性。
原始类型用第一个限定的类型变量来代替。如果没指定限定类型则用Object类型代替。比如T extends Comparable & Serializable,其原始类型为第一个限定类型Comparable。
5.约束与局限性
(1). 不能用基本类型实例化类型参数。原因显然是由于在编译时的类型擦除引起的。Object不能存储基本类型的值。
(2). 运行时类型查询只适用于原始类型。如if(a instanceof GenericClass<T>)同if(a instanceof GenericClass<String>)是一样的,他们都是Objectt类型,原始类型。
(3). 不能抛出也不能捕获泛型实例。事实上,泛型类扩展Throwable都不合法,也不能在catch语句中使用类型变量。
(4).参数化类型的娄组不合法。主要也是由开擦除后类型匹配问题。
(5). 不能实例化类型变量。如new T()是不合法的。
(6). 泛型类型的静态上下文中类型变量无效。
6. 能配符类型
如:GenerticClass<? extends Comparable>表示任何泛型类型,其类型方法是实现了Comparable接口的任意。