Java获取通用类型的集合

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19253121/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 15:29:44  来源:igfitidea点击:

Java get generic type of collection

javagenericsreflection

提问by Gumba

My project include reflection and i'm currently handling with generic types. I've managed to get the generic type from a List(java.util.List) with:

我的项目包括反射,我目前正在处理泛型类型。我已经设法从 List(java.util.List) 获取泛型类型:

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

I also have a Collection<String>and it turns out that Collection can NOTbe cast to ParameterizedType.

我也有一个Collection<String>,结果表明不能将Collection 转换为 ParameterizedType。

Someone have an idea how to get the String (or whatever type that will be) out of the collection?

有人知道如何从集合中获取字符串(或任何类型)?

I've been reading about java erasure so i'm aware of that, but after getting the generic out of the List, i thought that maybe someone knows another 'trick'.

我一直在阅读有关 Java 擦除的内容,所以我知道这一点,但是在从列表中取出泛型之后,我想也许有人知道另一个“技巧”。

Thanks.

谢谢。

EDITED: I'm iterating over all of the fields of the class with:

已编辑:我正在使用以下内容迭代该类的所有字段:

for (Field originalField : someClass.getDeclaredFields())

And then when i'm facing some List<String>Field, with the above code i getting the Stringas the subClass variable.

然后当我面对某个List<String>Field 时,使用上面的代码,我将其String作为 subClass 变量。

采纳答案by Rohit Jain

Your approach is fine. It should work for both List<String>and Collection<String>. For example see this sample code:

你的方法没问题。它应该适用于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());
                }
            }
        }
    }
}

this prints out:

这打印出来:

java.lang.String
java.lang.String

回答by Giulio Franco

As far as I know, Java fully erases the type, so the compiled code has no traces of the value you assigned to parameter types. All the parametric types are translated to concrete types, with type castings and things like that

据我所知,Java 完全擦除了类型,因此编译后的代码没有您分配给参数类型的值的痕迹。所有参数类型都被转换为具体类型,类型转换和类似的东西

In the code I've seen so far, when a class need to know the value of its generic type, it forces an object of that type (or the class) to be passed as a parameter. Something like:

在我目前看到的代码中,当一个类需要知道其泛型类型的值时,它会强制将该类型(或类)的对象作为参数传递。就像是:

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

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

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

回答by Jonathan

You'll need to resolve the ParameterizedType using whatever type it was defined on. For example, using TypeTools:

您需要使用定义的任何类型来解析 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;

Here the value of Twas defined in StringFoo, so we can use TypeResolverto resolve the raw class for our field's type using StringFoo

这里的值T是在 StringFoo 中定义的,因此我们可以使用以下TypeResolver方法解析字段类型的原始类StringFoo