Java从另一个数组的通用运行时类型创建数组

时间:2013-02-13 17:14:54

标签: java arrays generics

我有以下代码合并两个数组,并且应该处理除基元之外的任何类型。

@SuppressWarnings("unchecked")
public static synchronized <E> E[]  aryMergeNoDup(E[]... arys){
    HashSet<E> hs = new HashSet<E>();
        for(E[] ary : arys) {
            if(ary == null) continue;
            for(E item : ary) {
                if(item != null) hs.add(item);
            }
        }
        hs.remove(null);
        return hs.toArray((E[]) Array.newInstance(
                arys.getClass().getComponentType(),hs.size()));
}

然而,当代码运行时,它会生成此异常:

java.lang.ArrayStoreException: java.lang.String
  at java.util.AbstractCollection.toArray(AbstractCollection.java:188)
  at util.Utils.aryMergeNoDup(Utils.java:197)

变量arys的运行时类型是String [];但是,当我用arys.getClass().getComponentType()替换String.class时,代码运行正常。

但是,该方法只能用于字符串,因为这样。我看不出有什么问题,因为它们都应该引用java.lang.String

抛出异常的AbstractCollection.java:188中的行是:

r[i] = (T)it.next();

public <T> T[] toArray(T[] a) {
    // Estimate size of array; be prepared to see more or fewer elements
    int size = size();
    T[] r = a.length >= size ? a :
              (T[])java.lang.reflect.Array
              .newInstance(a.getClass().getComponentType(), size);
    Iterator<E> it = iterator();

    for (int i = 0; i < r.length; i++) {
        if (! it.hasNext()) { // fewer elements than expected
            if (a != r)
                return Arrays.copyOf(r, i);
            r[i] = null; // null-terminate
            return r;
        }
        r[i] = (T)it.next();
    }
    return it.hasNext() ? finishToArray(r, it) : r;
}

3 个答案:

答案 0 :(得分:3)

由于它是varargs,arys的运行时类型将是E[][],而不是E[]。因此,您可能需要arys.getClass().getComponentType().getComponentType()作为Array.newInstance的参数。

答案 1 :(得分:0)

我认为问题是arys类似于数组数组。因此,arys.getClass().getComponentType()可能String[],而不是String

答案 2 :(得分:0)

你有两个独立的事情在这里互动。首先,您正在使用varargs,它们将其参数包装在动态生成的数组中。因此arys的类型将是E [] [],因此获取组件类型将是E []。其次,泛型意味着E在运行时被擦除为Object,因此即使两个getComponentType调用也不会削减它 - 除非你总是返回Object []。

你可以做的是使用arys [0]的组件类型(如果存在)。这甚至不适用于所有情况,因为例如第二个数组的类型可能是超类,或第一个类的兄弟,与第一类型的数组不兼容。

要解决这个问题,你可以通过检查所有数组的类型来计算最小上限类型,但是如果你的典型用法是同一类型的数组,我认为这对于“第一类胜利”来说是过度的。