考虑以下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;
}
首先,从名为'Test'的类开始,我以递归方式搜索所有字段,这些字段用'MyAnnotation'注释,其类型派生自'java.lang.Collection'。对于给定的示例,结果将是:
很明显,第一个只能为其元素取字符串,而第二个只能取整数。
我的问题是:查找使用“MyAnnotation”注释的所有Collection字段以及告诉其元素类型的最佳(最简单)方法是什么?
从类型java.lang.Collection中查找带注释的字段不是问题。但是,对于给定的示例,我们如何得到看起来像下一个的结果?
我尝试了几种方法,总是将'Object'作为集合的元素类型而不是'String'。
我真的坚持这个。 非常感谢提前!
答案 0 :(得分:8)
可能你可以尝试这样:
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);
}
}
这将返回fieldArgClass = java.lang.String
答案 1 :(得分:0)
由于Java的类型擦除,这是不可能的。编译时,泛型类型将被原始类型替换,结果如下:
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;
将被翻译为:
Test test = new Test();
// The generic type is erased here...
List a = test.foo1.bar;
// ...and a cast is added here
String b = (String) a.get(0);
Integer b = (Integer) test.foo2.a;
长话短说:你无法检索那种类型,因为它在编译时被丢弃了。