提示二十九
2022-07-07 本文已影响0人
飞絮搅青冥
提示二十九: 优先考虑泛型。
这一章中,作者主要通过举例讲解了一个的简单堆栈实现。
class Stack {
private 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);
}
}
因为这里的element对象是Object数组,所以使用的时候会需要强制类型转化,所以作者就提出了两种泛型化的方法。
一种是将Object[]强转成E[]:
public class Stack<E> {
private E[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
@SuppressWarnings("unchecked")
public Stack() {
elements = (E[]) new Object[DEFAULT_INITIAL_CAPACITY];
}
另外一种是将elements从E[] 改成Object[], 数组取元素时再把Object转化成E。
private Object[] elements;
private int size = 0;
private static final int DEFAULT_INITIAL_CAPACITY = 16;
public Stack() {
elements = new Object[DEFAULT_INITIAL_CAPACITY];
}
public E pop() {
if (size == 0)
throw new EmptyStackException();
// push requires elements to be of type E, so cast is correct
@SuppressWarnings("unchecked") E result =
(E) elements[--size];
elements[size] = null; // Eliminate obsolete reference
return result;
}
第一种可读性更强,但会造成堆污染:数组编译和运行时类型不匹配。第二种就不会造成堆污染。总之,泛型类型比需要在客户端代码中强制转换的类型更安全,更易于使用。在设计新类的时候,要确保它们不需要这种转换就可以使用。
但是如果不用数组,而采用列表,那么上面这个方法会容易很多。但如果考虑到堆栈是基础的数据结构,如果被广泛使用可能会需要考虑性能,数组又比列表更加优秀,总之还是要权衡多方因素。但是我们实际编码过程中,由于是客户端开发为主,基本不会去写非常底层的工具,所以我一般都是无脑选择列表的,可能以后开发的时候也要多考虑考虑。