一般来说,将集合声明参数化,使用JDK提供的泛型或者泛型方法都不困难,,编写自己的泛型会比较困难一些,但是值得花时间去学习如何编写。
考虑之前的一个例子,堆栈的实现
// Initial attempt to generify Stack = won't compile!
public class Stack<E> {
private E[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new E[DEFAULT_INITIAL_CAPACITY];//error
}
public void push(E e) {
ensureCapacity();
elements[size++] = e;
}
public E pop() {
if (size == 0)
throw new EmptyStackException();
E result = elements[--size];
elements[size] = null;
return result;
}
public boolean isEmpty() {
return size == 0;
}
private void ensureCapacity() {
if (elements.length == size)
elements = Arrays.copyOf(elements, 2 * size + 1);
}
}
如25条所述,你不能创建不可具化的类型数组,每当编写用数组支持的泛型时,都会出现这个问题。解决办法有两个
1.直接绕过创建泛型数组的禁令:创建一个object的数组,直接将它转化成泛型数组类型。现在错误消除了,但是又会出现一条警告
elements = (E[])new Object[DEFAULT_INITIAL_CAPACITY];
warnings:[unchecked] cast found object[] ,required e[]
编译器不可能证明你的程序是类型安全的,但是你可以证明。你自己必须确保未受检查的转换不会危及到程序的安全性。这个数组中保存的唯一元素,是传给push方法的那些元素,他们的类型是E,因此是绝对安全,不会发生转换异常的,一旦证明了这点就需要尽可能小的范围去消除警告,代码如下
@SuppressWarnings("unchecked")
public Stack() {
// elements = new E[DEFAULT_INITIAL_CAPACITY];
elements = (E[])new Object[DEFAULT_INITIAL_CAPACITY];
}
2.将elements的类型变成object[],这个时候回遇到新的异常

解决方法:
public E pop() {
if (size == 0)
throw new EmptyStackException();
@SuppressWarnings("unchecked")
E result = (E)elements[--size];
elements[size] = null;
return result;
}
这里就没有必要在方法上加注解!!
总之,使用泛型比使用需要在客户端代码中进行转化的类型来的更安全。也更容易,在设计新类的时候,要确保它们不需要这种转换就可以使用。这通常意味着要把类做成是泛型的。
网友评论