2013-02-13 55 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

相關問題