web-dev-qa-db-ja.com

Java不明なタイプのジェネリックリストに追加する

Javaで、これまでに遭遇したことのない何かに遭遇しました。つまり、既知の型を割り当てずに、実行時にArrayListクラスなどの新しいインスタンスを作成してから、データを追加する必要があります。リストに追加します。少しあいまいに聞こえるので、次に例を示します。

Class<?> c = i.getClass();

Constructor<?> con = ArrayList.class.getConstructor();
ArrayList<?> al = (ArrayList<?>)con.newInstance();

al.add("something");

ジェネリックを使用するのではなく、これを行う理由は、ジェネリックがすでに頻繁に使用されており、この例の「i」変数がタイプ「?」として使用されるためです。別のジェネリックを投入したくないのは、ユーザーの作業が増え、最終的な設計の柔軟性が大幅に低下するためです。以下のようなものを使用する方法はありますか(注:以下のものは機能しません)。誰かアイデアがありますか?

ArrayList<c> al = (ArrayList<c>)con.newInstance();
13
ars265

ワイルドカードジェネリックを使用して定義されたコレクションにオブジェクトを追加することはできません。 このスレッド あなたを助けるかもしれません。

実際、あなたはすべてのコレクションのスーパータイプであるコレクションを作成しているので、ジェネリックの任意のコレクションに割り当てることができます。しかし、コンパイラが追加するもののタイプをチェックする方法がないため、一般的すぎてあらゆる種類の追加操作を許可できません。そして、それはまさにジェネリックスが意味するものです:型チェック。

スレッドを読んで、やりたいことにも当てはまるかどうかを確認することをお勧めします。

コレクションは一般的すぎて何も追加できません。問題は、割り当ての右側(シングルトンまたはリフレクションを使用)とは関係ありません。ワイルドカードを使用した左側の宣言タイプにあります。

12
Snicolas

私があなたの言いたいことを理解すると、あなたはコンパイル時に未知のクラスCを持っていて、タイプセーフな方法でArrayList<C>を作成したいと思っています。これは可能です:

Class<?> c = ...;
ArrayList<?> al = listOf(c);

static <T> ArrayList<T> listOf(Class<T> clazz)
{
    return new ArrayList<T>();
}

これは理論的に正しい方法です。しかし、誰が気にします。型消去については誰もが知っていますが、Javaが型消去を削除し、型パラメーターのランタイム型を追加する可能性はありません。したがって、何を知っている限り、raw型を使用して自由にキャストできます。あなたがやっている。

8
irreputable

_ArrayList<Object>_を使用するだけで、何でもadd()できます。

5
Bohemian