java中优先考虑泛型----禁止数组类型的未受检转换和禁止标量类型(Effective java code)

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”)

猜你喜欢

转载自blog.csdn.net/soullines/article/details/80694494