-2

如何使以下代码完全通用?

为什么我不允许写:

private E[]store = new E[length];

import java.util.Arrays;
public class MyArrayList<E> {
    private int size = 0;
    private int length = 10;

    private Object [] store = new Object[length];
        public E get(int index){
        return (E)store[index];
    }

    public void add(E item){
        if(size >= store.length -5){
            increment(store);
        }
        store[size++] = item;
    }

    private <T> void increment(T[] store2) {
        store = Arrays.copyOf(store2, store2.length * 2);
    }

    public int size(){
        return size;
    }
}
4

2 回答 2

2

只能声明组件类型为类型参数的数组变量,但不能创建对应的数组对象。由于类型擦除,运行时的类型E未知。编译器不知道如何创建未知组件类型的数组。

同样,您不能创建具体参数化类型的数组。

一种解决方法是使用Array.newInstance方法:

Class<E> clazz;
E[] array = (E[])Array.newInstance(clazz, length) ;

但是,这会给您一个Unchecked Cast警告,因为Array.newInstance返回一个Object,并且您将其转换为E[]. @SuppressWarnings您可以使用注释来抑制警告。但是,您需要clazz在该方法中传递参数,该参数应该是E类型参数的类类型。


数组和泛型类型之间有一个主要区别 - 即,数组被具体化(正如@Marko 在他的回答中所述)我要添加一段,来自《有效的 Java -关于这个主题的第 29条》一书:

这意味着数组在运行时知道并强制执行它们的元素类型。如上所述,如果您尝试将 String 存储到 Long 数组中,您将收到 ArrayStoreException。相比之下,泛型是通过擦除实现的 [JLS, 4.6]。这意味着它们仅在编译时强制执行其类型约束,并在运行时丢弃(或擦除)其元素类型信息。擦除是允许泛型类型与不使用泛型的遗留代码自由互操作的原因(第 23 条)。

由于这些根本差异,数组和泛型不能很好地混合。例如,创建泛型类型、参数化类型或类型参数的数组是非法的。这些数组创建表达式都不合法:new List<E>[], new List<String>[], new E[]. 所有这些都会在编译时导致通用数组创建错误。

于 2013-08-17T17:49:38.197 回答
2

数组元素类型,与泛型类型参数不同,是一个具体化的实体。换句话说,new Integer[]创建与 不同种类的对象new Double[]。与此相反,new ArrayList<Integer>()创建与 完全相同的对象new ArrayList<Double>()

由于泛型类型参数已从运行时代码中删除,JVM 无法实例化您想要的正确类型的数组。

于 2013-08-17T17:49:40.980 回答