优先考虑泛型

2018-07-26  本文已影响0人  没走过的二丁目

一般来说,将集合声明参数化,使用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[],这个时候回遇到新的异常


image.png

解决方法:

 public E pop() {
        if (size == 0)
            throw new EmptyStackException();
        @SuppressWarnings("unchecked")
        E result = (E)elements[--size];
        elements[size] = null;
        return result;
    }

这里就没有必要在方法上加注解!!

总之,使用泛型比使用需要在客户端代码中进行转化的类型来的更安全。也更容易,在设计新类的时候,要确保它们不需要这种转换就可以使用。这通常意味着要把类做成是泛型的。

上一篇 下一篇

猜你喜欢

热点阅读