2013-02-13 57 views
2

我有下面的代码,它合并两个数组,并且应该处理除了原语之外的任何类型。当代码运行Java从另一个数组的通用运行时类型创建数组

@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.class替换arys.getClass().getComponentType()时,代码运行良好。

但是,该方法只能用于字符串,因为这是pf。我看不出有什么问题,因为他们都应该参考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

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

+0

arys.getClass()。getComponentType()。getComponentType()是一种享受! – user1467885 2013-02-13 18:53:04

0

相信问题是arys是像数组的数组。所以可能arys.getClass().getComponentType()String[],而不是String

0

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

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

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

+0

“其次,泛型意味着E在运行时被擦除为Object,所以即使两个getComponentType调用也不会削减它 - 除非您始终返回Object []。这没有意义。 'arys'的类型是'E [] []',这意味着'arys'的运行时类型,如果不是'null',保证是'E [] []'或者一个子类型,除非你做了某事不安全的地方。 – newacct 2013-02-13 20:12:36

+0

当然。我说“'E'在运行时被擦除为'Object'',而不是''E [] []'在运行时被擦除为'Object''。重点是你不能使用'arys.getComponentType()。getComponentType()'来确定E的类型,而不是传入数组的运行时类型。 – BeeOnRope 2013-02-13 20:47:55

+0

好吧,你是对的 - 可变参数数组的运行时类型似乎是基于传递对象的编译时间类型来选择的 - 我以为它总是会是Object [] []。 所以'getComponentType()。getComponentType()'将反映该编译时选择。如果调用站点中的数组的编译时类型不等于其派生最多的运行时类型,那么使用元素的类型仍然会选择更具体的数组类型。 – BeeOnRope 2013-02-13 21:08:08

相关问题