パラメータ化されたクラスインスタンスを取得する方法

StackOverflow https://stackoverflow.com/questions/71585

  •  09-06-2019
  •  | 
  •  

質問

ジェネリックスが導入されてから、Class がパラメータ化され、List.class が Class<List> を生成するようになりました。これは明らかです。

私が理解できないのは、それ自体がパラメータ化されたタイプのクラスのインスタンスを取得する方法です。クラス<リスト<文字列>>。このスニペットのように:

public class GenTest {
    static <T> T instantiate(Class<T> clazz) throws Exception {
        return clazz.newInstance();
    }
    public static void main(String[] args) throws Exception {
        // Is there a way to avoid waring on the line below
        // without using  @SuppressWarnings("unchecked")?
        // ArrayList.class is Class<ArrayList>, but I would like to
        // pass in Class<ArrayList<String>>
        ArrayList<String> l = GenTest.instantiate(ArrayList.class);
    }
}

私はこの問題のバリエーションに頻繁に遭遇しますが、単に何かを見逃しているだけなのか、それとも本当に良い方法がないのか、まだわかりません。ご提案ありがとうございます。

役に立ちましたか?

解決

Class クラスは、型の実行時表現です。パラメーター化された型は実行時に型が消去されるため、Class のクラス オブジェクトは Class<List<Integer>> および Class<List<String>> のクラス オブジェクトと同じになります。

.class 表記を使用してインスタンスを作成できない理由は、これがクラス リテラルに使用される特別な構文であるためです。の Java言語仕様 特に、型がパラメーター化されている場合、この構文は禁止されています。そのため、List<String>.class は許可されません。

他のヒント

クラスは、クラス ローダーによってロードされたクラス (生の型) を表します。パラメータ化された型を表すには、java.lang.reflect.ParameterizedType を使用します。

あなたがやろうとしていることができるとは思えません。まず、インスタンス化メソッドはパラメータ化された型を扱っていることを知りません (java.util.Date.class を渡すことも簡単にできます)。第 2 に、消去があるため、実行時にパラメーター化された型で特に特殊なことを行うのは困難または不可能です。

別の方法で問題にアプローチする場合は、型推論など、他にも実行できる小さなトリックがあります。

public class GenTest
{
    private static <E> List<E> createList()
    {
        return new ArrayList<E>();
    }

    public static void main(String[] args)
    {
        List<String> list = createList();
        List<Integer> list2 = createList();
    }
}

できることはインスタンス化することだけです List<String> 直接 そしてそれを呼び出します getClass():

instantiate(new List<String>() { ... }.getClass());

次のような複数の抽象メソッドを持つ型の場合 List, 、これはかなり厄介です。しかし、残念なことに、サブクラスのコンストラクターを呼び出すと( new ArrayList<String>) またはファクトリーメソッド (Collections.<String>emptyList())機能しません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top