4

重複の可能性:
Java の使い方: 汎用配列の作成

T[]Javaで型の配列を作成するには? Arrays.newInstance()のオブジェクトがないので使用できませんClass<T>newInstanceどこかにジェネリックバージョンはありますか?

私のメソッドのプロトタイプは次のとおりです。

public <T> T[][] distribute(T ... balls) {
   T[][] answer = ????

   // filling answer with data

   return answer;

}

アップデート

上記の例で申し訳ありませんが、からクラスを受講できますballs。しかし、そのような変数がないとします。

public <T> T[][] distribute() {
   T[][] answer = ????

   // filling answer with data

   return answer;

}

また

class<T> {
   public T[][] distribute() {

      T[][] answer = ????

      // filling answer with data

      return answer;

   }
}

UPDATE2

次の例も機能しません。

public abstract class GenericArray<T> {

abstract public T create();

public T[] gen1() {
    T[] ans = (T[]) new Object[3];
    ans[0] = create();
    ans[1] = create();
    ans[2] = create();
    return ans;
}

public Integer[] gen2() {
    Integer[] ans = new Integer[3];
    ans[0] = new Integer(0);
    ans[1] = new Integer(0);
    ans[2] = new Integer(0);
    return ans;
}

public static void main(String[] args) {

    GenericArray<Integer> a = new GenericArray<Integer>() {

        @Override
        public Integer create() {
            return new Integer(0);
        }
    };

    Integer[] b = a.gen2();
    Integer[] c = a.gen1(); // this causes ClassCastException

    System.out.println("done");

}

}
4

4 に答える 4

6

1. ないArrays_ Generic

2.その理由Arraysは、コンパイル時だけでなく実行時もチェックされますCollections。ここで、汎用であり、コンパイル時にのみチェックされます....

于 2012-08-18T17:09:10.283 に答える
1

(T[][]) new Object[size][size]

于 2012-08-18T17:09:57.130 に答える
1

あなたが求めるものは不可能です。配列は実行時にそのコンポーネント タイプを認識しており、異なるコンポーネント タイプの配列は異なるランタイム タイプです。そのため、配列を作成するときは、実行時にコンポーネントの型を知る必要があります。

あなたのメソッドはジェネリックであるため、呼び出し元は、このメソッドを呼び出すたびに、使用したい をコンパイラにT指示できます。Tしたがって、これがどれほどばかげているかを考えてみてください。

String[][] foo = this.<String>distribute();
Integer[][] bar = this.<Integer>distribute();

この右側のコンパイル済みコードは、2 つの行で同じです。これら.<String>はコンパイラへの単なるヒントであり、コンパイルされたコードには影響しません。したがって、これはがanddistribute()の両方である何かを返さなければならないことを意味します ( andは実行時の型として具体化されているため、実行時にチェックされます)。これを満たす唯一の値は です。String[][]Integer[][]String[][]Integer[][]null

(なぜこの問題が を返すメソッドで発生しないのかと尋ねるかもしれませんList<T>。答えは、配列とは異なり、List実行時にクラスが 1 つしかないためです。また、リストは実行時にコンポーネントの型を認識しません。したがって、anew ArrayList<Foo>()と anew ArrayList<Bar>()正確に実行時も同じなので、この問題はありません。)

ここで起こっていることの別の類推: つまり、配列型には、コンポーネント型の継承に従う継承パターンがあります。のサブクラスInteger[][]も同様ですObject[][]。実際、すべてT[][]が のサブクラスですObject[][]。とそのサブクラスの代わりに、一連のサブクラスを持つObject[][]非配列クラス を考えてみましょうMyBaseClassMyBaseClass次に、基本的に求めているのは、 (型パラメーターによって決定される)の未知のサブクラスのインスタンスを一般的に作成できるようにすることです。

<T extends MyBaseClass> T distribute() {
    T answer = //...?
    return answer;
}

なぜこれが不可能なのか、お分かりいただけると思います。

于 2012-08-18T19:39:14.810 に答える
0

Do:T[][] answer = (T[][]) new Object[][];
Tいずれにせよ、コンパイラによって に消去されObjectます。もちろん、配列のサイズを知る必要があります。

更新:
新しい例では、ここで例外が発生します:
Integer[] c = a.gen1(); // this causes ClassCastException
を にキャストしようとしているObject[]からInteger[]です。ありえない。
返されるのは、Object[]しかし参照を含むIntegerものです。したがって、次のことを行う必要があります。

Object[] c = a.gen1();
for(Object n:c){  
    Integer nn = (Integer) n;  
}  

nはですので、これで問題ありませんInteger
ただし、原則として、パラメーター化された型オブジェクトを収集する必要がある場合は、単純にArrayList. classリフレクションを介して配列をインスタンス化する実際のものさえないあなたの例では、それが唯一の賢明な選択です

于 2012-08-18T17:11:00.353 に答える