考虑第6条的简单堆栈实现:
public class Stack { pprivate Object[] elements; private int size = 0; private static final int DEFAULT_INITAL_CAPACITY = 16; public Stack() { elements = new Object[DEFAULT_INITAL_CAPACITY]; } public void push(Object e) { ensureCapacity(); elements[size++] = e; } public Object pop() { if(size == 0) { throw new EmptyStackException(); } Object 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); }}
将该类泛型化可以提高类型的安全性,方便客户端使用(无需显式强制转换类型)
首先用类型参数替换所有的Object类型:
public class Stack{ pprivate E[] elements; private int size = 0; private static final int DEFAULT_INITAL_CAPACITY = 16; public Stack() { elements = new E[DEFAULT_INITAL_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; } public boolean isEmpty() { return size == 0; } private void ensureCapacity() { if(elements.length == size) elements = Arrays.copyOf(elements, 2 * size + 1); }}
由于不能创建不可具体化类型的数组,所有有错误(new E[DEFAULT)INITIAL_CAP]是不允许的)
解决方法:
1.创建一个Object数组,并将它转换成泛型数组类型:
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
错误变成一条警告,因为可以保证类型安全,所以可以用SupressWarning注释忽略掉该警告。
2.将elements域的类型从E[]改为Object[]:
private Object[] elements; E result = (E) elements[--size];
产生一条警告,因为可以保证类型安全,所以所以可以用SupressWarning注释忽略掉该警告。
实际中选择第二种方法较多,因为pop方法经常会被调用,频繁地类型转换会耗费时间。
在25条中,鼓励优先使用列表而非数组。实际上并不总能在泛型中使用列表。为了提高性能,列表不是Java提供的基本实现,如ArrayList就需要在数组上实现,而某些类,如HashMap为了提高性能,也在数组上实现。