使用Java反射查找集合';s元素类型?

使用Java反射查找集合';s元素类型?,java,Java,考虑以下Java代码: public class Test { private Foo< String, String > foo1; private Foo< Integer, Integer > foo2; } public class Foo< T, V > { private Bar< V > bar; private T a; } public class Bar< T > { @M

考虑以下Java代码:

public class Test
{
    private Foo< String, String > foo1;
    private Foo< Integer, Integer > foo2;
}

public class Foo< T, V >
{
    private Bar< V > bar;
    private T a;
}

public class Bar< T >
{
    @MyAnnotation
    private List< T > list;
}
公共类测试
{
私有Foofoo1;
私有Foofoo2;
}
公开课Foo
{
私人酒吧酒吧;
私人旅行社;
}
公共类酒吧
{
@MyAnnotation
私有列表List;
}
首先,从名为“Test”的类开始,我递归搜索所有字段,这些字段用“MyAnnotation”注释,其类型派生自“java.lang.Collection”。对于给定的示例,结果将是:

  • Test.foo1.bar.list
  • Test.foo2.bar.list
很明显,第一个只能接受其元素的字符串,而第二个只能接受整数

我的问题是:找到用“MyAnnotation”注释的所有集合字段并告诉它们的元素类型的最佳(最简单)方法是什么?

从java.lang.Collection类型中查找带注释的字段不是问题。但是,对于给定的示例,我们如何得到如下结果呢

  • Test.foo1.bar.list
  • Test.foo2.bar.list
我尝试过几种方法,它们总是将“Object”作为集合的元素类型,而不是“String”

我真的被这件事缠住了。
非常感谢

也许你可以这样尝试:

Field field = Test1.class.getField("list");

Type genericFieldType = field.getGenericType();

if(genericFieldType instanceof ParameterizedType){
    ParameterizedType aType = (ParameterizedType) genericFieldType;
    Type[] fieldArgTypes = aType.getActualTypeArguments();
    for(Type fieldArgType : fieldArgTypes){
        Class fieldArgClass = (Class) fieldArgType;
        System.out.println("fieldArgClass = " + fieldArgClass);
    }
}
public class Test
{
    private Foo foo1;
    private Foo foo2;
}

public class Foo
{
    private Bar bar;
    private Object a;
}

public class Bar
{
    @MyAnnotation
    private List list;
}

这将返回
fieldArgClass=java.lang.String

由于java的类型擦除,这是不可能的。编译时,泛型类型将替换为原始类型,结果如下:

Field field = Test1.class.getField("list");

Type genericFieldType = field.getGenericType();

if(genericFieldType instanceof ParameterizedType){
    ParameterizedType aType = (ParameterizedType) genericFieldType;
    Type[] fieldArgTypes = aType.getActualTypeArguments();
    for(Type fieldArgType : fieldArgTypes){
        Class fieldArgClass = (Class) fieldArgType;
        System.out.println("fieldArgClass = " + fieldArgClass);
    }
}
public class Test
{
    private Foo foo1;
    private Foo foo2;
}

public class Foo
{
    private Bar bar;
    private Object a;
}

public class Bar
{
    @MyAnnotation
    private List list;
}
然后在直接使用
foo1
foo2
的地方填写实际类型。例如,以下代码:

Test test = new Test();
List<String> a = test.foo1.bar;
String b = a.get(0);
Integer b = test.foo2.a;

长话短说:您无法检索该类型,因为它在编译时被丢弃。

您尝试过吗?相关:@MattiasBuelens您链接的主题处理不同类型的问题。@user1444073 My bad,没有在字段声明中发现
。您的类“Test1”,是我的类“Test”还是“Bar”?你的Test.Bar.foo与这里有什么关系?或者你能详细说明一下吗bit@MatthiasWuttke我不知道你想说什么,你真的没怎么评论。这个问题是关于获取泛型类型信息的“技巧”,但它依赖于始终使用(匿名)超类来填充泛型类型,并且它在所有情况下都不起作用(例如,
new ArrayList(){};
不起作用)。我仍然不明白这与这个问题有什么关系……我发现这两个问题都是通过谷歌提出的,我链接的第二个问题帮助我解决了问题。(我需要找出集合字段的泛型类型参数。)虽然您的答案肯定是正确的,并且有助于理解Java类型擦除,但我链接的问题解决了我的问题。我添加评论是为了帮助其他人,但应该添加更多的链接。我不想踩到你的屁股,所以请接受我的道歉。@MatthiasWuttke好的,没问题。谢谢你的解释。:-)