Java泛型和数组

时间:2010-12-16 12:33:31

标签: java generics

当我针对单元测试运行时,下面的代码段仍然有意义。我在标有“>>>>”的行上得到一个ClassCastException(Object不能转换为String)。这种类型的操作可以通用吗?

public class ArrayUtils<E> {

    public static <E> E[] appendToArray(E[] array, E item) {
        E[] result = (E[])new Object[array.length+1];
        for(int i=0; i < array.length; i++ ) {
            result[i] = array[i];
        }
        result[result.length-1] = item;
        return result;
    }

}

   @Test
   public void testAppendToArray() {
       String[] array = new String[1];
       array[0] = "a";

       assertSame("Array is not correct length.", 1, array.length );
>>>>   String[] appendToArray = ArrayUtils.<String>appendToArray(array, "b");
       assertSame("Array is not correct length.", 2, appendToArray.length );
    }

5 个答案:

答案 0 :(得分:5)

您不应该使用新的Object []创建数组。您应该使用Array.newInstance(Class clazz, int length)代替。

答案 1 :(得分:1)

你将Object投射到String,IOW,一个继承的超类。 它总是被禁止的。正如AlexR建议的那样,请使用Arrays.newInstance()。但在这种情况下,您必须传递一个对象类,如下所示:

ArrayUtils.<String>append(array, "b", String.class);

我建议你不要尝试实现动态扩展数组的这种标准行为:它已经在ArrayList类中实现了。您可以查看源代码以了解它如何处理泛型。

答案 2 :(得分:0)

我不知道这个代码是什么,但它给垃圾收集器带来了负担,因为要添加一个元素,你需要分配一个新的数组。您应该使用List的任何实现,例如ArrayList

答案 3 :(得分:0)

遗憾的是,无法在Java中动态创建泛型类型的数组,因为与泛型类型(E)相关的信息不会在运行时传输,因此无法知道什么类型的要创建的数组。

为了解决这个问题,我建议对one used in collections library

采用类似的解决方案
T[] java.util.List.toArray(T[] array)

方法。也就是说,不是在appendToArray函数中创建新数组,而是从外部传递它。那就是:

public static <E> E[] appendToArray(E[] array, E item, E[] newArray) {
  ... your code ...
}

@Test
public void test(){
  appendToArray(array, "b", new String[array.length+1]);
}

我知道这看起来并不像其他解决方案那么好,但它的类型安全,并且具有更好的性能,因为它不会求助于反射。出于这个原因,建议您使用

T[] java.util.List.toArray(T[] array)

方法超过它的反射等价

T[] java.util.List.toArray()

答案 4 :(得分:0)

正如其他人所说,您应该使用Array.newInstance()来创建正确类型的数组实例。更有用的是,您可以从原始数组的类中获取所需的组件类型。

另外,我使用System.arraycopy()简化了复制。

public static <E> E[] appendToArray(E[] array, E item) {
    E[] result = (E[])java.lang.reflect.Array.newInstance(array.getClass().getComponentType(), array.length+1);
    System.arraycopy(array, 0, result, 0, array.length);
    result[result.length-1] = item;
    return result;
}

在Java 1.6+中,您可以这样做:

public static <E> E[] appendToArray(E[] array, E item) {
    E[] result = java.util.Arrays.copyOf(array, array.length+1);
    result[result.length-1] = item;
    return result;
}