Effective第26条中有提到优先考虑泛型,但是由于java会设计到数组所以会有泛型兼容数组的问题;首先泛型不应该与数组复用,但是java的历史原因,泛型的问世比较晚,必须兼容旧版本代码!所以有些情况必须拒绝受检!!!!
我们以stack为例:
在泛型没有问世之前是这样的:
public class Stack {
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(Object e) {
ensureCapacity();
elements[size++] = e;
}
public Object pop() {
if (size == 0)
throw new EmptyStackException();
E result = elements[--size];
elements[size] = null;
return result;
}
.......
}
在java1.6之前,Object兼容其他类型,需要外部强转,泛型出现时,可以指定参数类型,并且在编译器受检;
所以Stack应该接收泛型类型的制定:
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];
}
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;
}
.......
}
但是由于泛型就不可以具体实例化,所以下面这一句会抛出error:
elements = new E[DEFAULT_INITIAL_CAPACITY];
在Effective java中提出两种方案,来解决这个问题:
1.方案一:禁止数组类型的未受检转换
private Object[] elements;
@SuppressWarnings("unchecked")
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
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;
}
我们把:
elements = new E[DEFAULT_INITIAL_CAPACITY] —>
elements = (E[])new Object[DEFAULT_INITIAL_CAPACITY]
这里用Object实例化数组,然后使用E[]进行强转,但是会抛出:
warn:[unchecked] unchecked cast
数组类型未受检,所以我们禁止泛型受检 @SuppressWarnings(“unchecked”)
1.方案二:禁止标量类型
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public void push(E e) {
ensureCapacity();
elements[size++] = e;
}
public E pop() {
if (size == 0)
throw new EmptyStackException();
@SuppressWarnings("unchecked")E result =
(E)lements[--size];
elements[size] = null;
return result;
}
方案二中数组就是一个Object的数组,但是在pop元素时候会对数组中的每一个标量进行E泛型的强转,然后进行类型转化,同第一种情况,在取元素时候会有类型未受检的warn,所以在元素的标量之前: @SuppressWarnings(“unchecked”)