2

2つの配列をマージし、プリミティブ以外のすべての型を処理する必要がある次のコードがあります。

@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

ただし、このメソッドは文字列にのみ使用できます。これは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;
}
4

3 に答える 3

3

これはvarargsであるため、の実行時タイプはではなく、にarysなります。したがって、おそらくへの引数として必要です。E[][]E[]arys.getClass().getComponentType().getComponentType()Array.newInstance

于 2013-02-13T17:21:03.553 に答える
0

問題はそれarysが配列の配列のようなものだと思います。したがって、おそらくはarys.getClass().getComponentType()でありString[]、ではありませんString

于 2013-02-13T17:20:41.100 に答える
0

ここでは、2つの別々のものが相互作用しています。まず、varargsを使用しています。これは、その場で生成された配列に引数をラップします。したがって、aryのタイプはE [] []になるため、getコンポーネントタイプはE[]になります。第二に、ジェネリックスは、実行時にEがObjectに消去されることを意味します。したがってgetComponentType、常にObject []を返すことに問題がない限り、2回の呼び出しでもEはカットされません。

できることは、arys[0]のコンポーネントタイプが存在する場合はそれを使用することです。たとえば、2番目の配列の型がスーパークラス、または最初の型の配列と互換性のない最初の割り当ての兄弟である可能性があるため、これはすべての場合に機能するわけではありません。

これを解決するには、すべての配列の型を調べることで最小上限型を計算できますが、通常の使用法が同じ型の配列である場合、これは「最初の型が勝つ」に対してやり過ぎだと思います。

于 2013-02-13T18:40:51.133 に答える