Javagenerics和数组
当我针对unit testing运行时,下面的代码片段仍然有意义。我在标有“>>>>”的行上得到一个ClassCastException(Object不能转换为String)。 这种类型的操作可以在通用中完成吗?
public class ArrayUtils { public static E[] appendToArray(E[] array, E item) { E[] result = (E[])new Object[array.length+1]; for(int i=0; i >>> String[] appendToArray = ArrayUtils.appendToArray(array, "b"); assertSame("Array is not correct length.", 2, appendToArray.length ); }
您不应该使用新的Object []创建数组。 您应该使用Array.newInstance(Class clazz, int length)
。
你正在将Object
为String
,IOW,一个inheritance的类的超类。 它总是被禁止的。 正如AlexR建议的那样,使用Arrays.newInstance()
。 但在这种情况下,你必须传递一个对象的类,如下所示:
ArrayUtils.append(array, "b", String.class);
我建议你不要尝试实现动态扩展数组的这种标准行为:它已经在ArrayList
类中实现了。 您可以查看源代码以了解它如何处理generics。
我不知道这个代码是什么,但它给垃圾收集器带来了负担,因为要添加一个元素,你需要分配一个新的数组。 您应该使用List
任何实现,例如, ArrayList
。
遗憾的是,无法在Java中动态创建generics类型的数组,因为与generics类型( E
)相关的信息不会在运行时传送,因此无法知道要创建的数组类型。
为了解决这个问题,我建议使用与集合库中使用的解决方案类似的解决方案
T[] java.util.List.toArray(T[] array)
方法。 也就是说,不是在appendToArray
函数中创建一个新数组,而是从外部传递它。 那是:
public static E[] appendToArray(E[] array, E item, E[] newArray) { ... your code ... } @Test public void test(){ appendToArray(array, "b", new String[array.length+1]); }
我知道这看起来不像其他解决方案那么好,但是它的类型安全,并且具有更好的性能,因为它不依赖于reflection。 出于这个原因,建议您使用
T[] java.util.List.toArray(T[] array)
它的reflection等效方法
T[] java.util.List.toArray()
正如其他人所说,您应该使用Array.newInstance()
来创建正确类型的数组的实例。 更有用的是,您可以从原始数组的类中获取所需的组件类型。
此外,我使用System.arraycopy()
简化了复制。
public static 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[] appendToArray(E[] array, E item) { E[] result = java.util.Arrays.copyOf(array, array.length+1); result[result.length-1] = item; return result; }