web-dev-qa-db-ja.com

Javaジェネリック型のコレクションを取得する

私のプロジェクトにはリフレクションが含まれており、現在ジェネリック型を扱っています。 List(Java.util.List)からジェネリック型を取得することができました:

if(originalField.getGenericType() instanceof ParameterizedType){
    ParameterizedType pt = (ParameterizedType) originalField.getGenericType();
    Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
}

私もCollection<String>を持っていますが、コレクションは[〜#〜] not [〜#〜] ParameterizedTypeにキャストできることがわかりました。

誰かがコレクションから文字列(またはそれがどんなタイプになるか)を取得する方法を知っていますか?

私はJava消去について読んでいるので、それを知っていますが、リストからジェネリックを取り出した後、誰かが別の「トリック」を知っているのではないかと思いました。

ありがとう。

編集済み:クラスのすべてのフィールドを次のように繰り返しています:

for (Field originalField : someClass.getDeclaredFields())

そして、いくつかのList<String>フィールドに直面しているとき、上記のコードでStringをsubClass変数として取得します。

12
Gumba

あなたのアプローチは大丈夫です。両方で機能するはずですList<String>およびCollection<String>。たとえば、次のサンプルコードを参照してください。

public class Demo {

    List<String> list = new ArrayList<>();
    Collection<String> coll = new ArrayList<>();

    public static void main(String args[]){

        Class<Demo> clazz = Demo.class;
        Field[] fields = clazz.getDeclaredFields();

        for (Field field: fields) {

            Type type = field.getGenericType();

            if (type instanceof ParameterizedType) {

                ParameterizedType pType = (ParameterizedType)type;
                Type[] arr = pType.getActualTypeArguments();

                for (Type tp: arr) {
                    Class<?> clzz = (Class<?>)tp;
                    System.out.println(clzz.getName());
                }
            }
        }
    }
}

これは印刷されます:

Java.lang.String
Java.lang.String
12
Rohit Jain

私の知る限り、Javaは型を完全に消去するため、コンパイルされたコードには、パラメーター型に割り当てた値のトレースがありません。すべてのパラメトリック型は、型キャストを使用して具象型に変換されます。そしてそのようなもの

これまで見てきたコードでは、クラスがジェネリック型の値を知る必要がある場合、その型のオブジェクト(またはクラス)をパラメーターとして渡すように強制します。何かのようなもの:

class A<T> {
    private final Class<T> parameterType;

    public A(Class<T> parCls) {
        parameterType = parCls;
    }

    public A(T tObj) {
        parameterType = tObj.getClass();
    }
}
1
Giulio Franco

定義されているタイプを使用して、ParameterizedTypeを解決する必要があります。たとえば、 TypeTools を使用します。

class Foo<T> {
  public T bar;
}

class StringFoo extends Foo<String> {}

Type barType = Foo.class.getDeclaredField("bar").getGenericType();
Class<?> t = TypeResolver.resolveRawClass(barType, StringFoo.class);
assert t == String.class;

ここでは、Tの値がStringFooで定義されているため、TypeResolverを使用して、StringFooを使用してフィールドの型のrawクラスを解決できます。

0
Jonathan