先看一个简单,未使用泛型实现的堆栈。
public class MyStack {
private Object[] elements;
private int size;
public static final int DEFAULT_INITIAL_CAPACITY = 16;
public MyStack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object o){
ensureCapacity();
elements[size++]=o;
}
public Object pop(){
if(size == 0){
throw new EmptyStackException();
}
Object result = elements[--size];
elements[size] = null;//手动垃圾回收
return result;
}
private void ensureCapacity() {
if(elements.length == size){
elements = Arrays.copyOf(elements,size*2+1);
}
}
}
尝试修改为泛型版本,第一步将Object全部替换为E
public MyStack2() {
elements = new E[DEFAULT_INITIAL_CAPACITY];
}
在这一步报错了,原来,不能初始化一个未知类型的泛型数组。ef提供了两种解决方案。
方案一:
@SuppressWarnings("unchecked")
public MyStack2() {
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
注意消除类型未检查警告。
方案二:
private Object[] elements;
public MyStack2() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
pop:
E result = (E)elements[--size];
两种各有其优势,前者在声明时强转,后者在取出时强转。这个根据具体需求而定,前者更危险,后者更耗时。其实个人感觉数组操作,区别也不是那么的大。
根据25条(泛型–列表优先于数组)的建议,能避免使用数组的地方,就避免吧,毕竟数组是协变(covariant)的。