疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java 泛型的学习


 

 
//使用泛型的优点
/**
使用泛型的主要优点是能够在编译时而不是运行时检测出错误。泛型类或方法允许用户指定可以
和这些类或方法一起工作的对象类型和一个包含数字的栈对象*/
/*防止不能一起工作的数据类型进行工作*/
 
 
//泛型的使用 ClassName<T> e = new ClassName<T>();如:
ArrayList<String> list = new ArrayList<String>();
 
 
1.定义泛型类和接口
public class ClassName <E> {
public ClassName() {
//构造方法
}
}
 
 
public interface InterfaceName <E> {
 
 
}
2.定义泛型方法
 
 
a.基本
public <E> returnVar method(E e) {
//传递参数类型必须合法才不会发生编译错误
}
 
 
使用
E e;
ClassName<E>.method(e) 来调用;
 
 
b.受限的泛型类型,将泛型指定为另一种类型的子类型
 
 
public <E extends fatherClass> returnVar method(E o1, E o2) {
//此时,只有当参数的传递类型为fatherClass 的子类,才不会发生编译错误
 
}
说明:
非受限类型<E> 与 <E extends Object> 是一样的
 
 
3.其他
(1)原始类型和向后兼容
a.可以使用泛型类而无需指定具体类型
ClassName e = new ClassName();
等价于
ClassName <Object> = new ClassName<Object>();
 
 
原始参数(raw type):不使用类型参数的泛型类
如:max(Comparable o1, Comparable o2) {
 
 
}
在Java的早期版本中,允许使用原始类型向后兼容(backward compatibility)
 
 
原始类型是不安全的,所以可以将上面的max函数改为
public <E extends Comparable> returnVar max(E o1, E o2) {
//这样的话,要调用max(),则需要 o1 与 o2 同为一种类型才不会发生编译错误
}
 
 
(2)通配泛型
 
 
a.原因
例如有如下类
public class ClassName {
public static void main(String[] args) {
ClassName1<Integer> e = new ClassName1<Integer>();
 
method(e);//这里会出现编译错误
}
 
public static returnVar method(ClassName1<Number> e) {
 
}
}
 
 
b.使用
在调用method(e)时,此时会出现编译错误,原因是:尽管Integer是Number的子类型,但
ClassName1<Integer> 不是ClassName1<Number>的子类。为了避免这个问题,可以使用
通配泛型。有三种形式
<?> 
<? extends T>
<? super T>
 
 
可修改上面程序的错误
public static returnVar method(ClassName1<? extends Number> e) {
 
 
}
 
 
<?> 为 <? extends Object> 的缩写
 
 
<? super T> 表示类型T 或者 T的父类型
 
 
(3)消除泛型和对泛型的限制
泛型是使用一种称为类型消除(type erasure)的方法实现的。编译器使用泛型类型信息
来编译代码,但是随后会消除它。
泛型存在于编译时,一旦编译器确认泛型类型安全使用的,就会将它转换为原始类型。
 
 
限制
 
 
1.不能使用 E e = new E(); 因为运行时泛型类型E是不可用的
2.不能使用 泛型参数创建数组
E[] e = new E[capacity]
可以这样规避
E[] e = (E[] ) new Object[capacity]
 
 
说明:会导致一个免疫的编译警告,因为不能保证在运行过程中类型转换能够成功。
不能使用 泛型类创建数组
ArrayList<String>[] list = new ArrayList<String>[10];
规避
ArrayList<String>[] list = new (ArrayList[String]) new Object[10];
同理 也会导致一个编译警告
3.在静态环境下不允许类的参数是泛型类型
public class ClassName<E> {
public static void m(E o1) {
//illegal
}
public static E o1;//illegal
static {
E o2;//illegal
}
}
4.异常类不能是泛型的
public class MyException<T> extends Exception {
/*
try {
}
catch (MyException ex){
}
*/
}