使用 Java 反射来查找集合的元素类型?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10945993/
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
Using Java Reflections to find Collection's element type?
提问by theV0ID
Consider the following Java code:
考虑以下 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;
}
First, starting with the class named 'Test', I'm searching all fields recursively, which are annotated with 'MyAnnotation' and whose type is derived from 'java.lang.Collection'. For the given example, the results would be:
首先,从名为“Test”的类开始,我递归地搜索所有字段,这些字段使用“MyAnnotation”进行注释并且其类型派生自“java.lang.Collection”。对于给定的示例,结果将是:
- Test.foo1.bar.list
- Test.foo2.bar.list
- 测试.foo1.bar.list
- 测试.foo2.bar.list
It's obviosly clear, that the first one can only take strings for its elements, whereas the second one can only take integers.
很明显,第一个只能为其元素取字符串,而第二个只能取整数。
My Question is: What is the best (easiest) way to find all Collection fields annotated with 'MyAnnotation' and tell their element type?
我的问题是:找到所有用“MyAnnotation”注释的集合字段并告诉它们的元素类型的最佳(最简单)方法是什么?
Finding annotated fields from type java.lang.Collection is not the problem. But how can we get a result which looks like the following one for the given example?
从类型 java.lang.Collection 中查找带注释的字段不是问题。但是,对于给定的示例,我们如何才能获得如下所示的结果?
- Test.foo1.bar.list< String >
- Test.foo2.bar.list< Integer >
- Test.foo1.bar.list<String>
- Test.foo2.bar.list<整数>
I've tried several approaches, which always gave me 'Object' as the collection's element type instead of 'String'.
我尝试了几种方法,这些方法总是给我“对象”作为集合的元素类型而不是“字符串”。
I'm really stuck on this. Many thanks in advance!
我真的坚持这一点。提前谢谢了!
采纳答案by Mattias Buelens
This is not possible due to Java's type erasure. When compiled, the generic types will be replaced by raw types, resulting in something like this:
由于 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;
}
The actual types are then filled in places where you are directly working with foo1
and foo2
. For example, the following code:
然后在您直接使用foo1
和 的地方填充实际类型foo2
。例如,以下代码:
Test test = new Test();
List<String> a = test.foo1.bar;
String b = a.get(0);
Integer b = test.foo2.a;
will be translated to something like:
将被翻译成类似的东西:
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;
Long story short: there's no way you can retrieve that type, since it is discarded at compile time.
长话短说:您无法检索该类型,因为它在编译时被丢弃。
回答by UVM
May be you can try like this:
也许你可以这样尝试:
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);
}
}
This will return fieldArgClass = java.lang.String
这将返回 fieldArgClass = java.lang.String