泛型列表属性,获取泛型的类型
我有一个具有属性 List
或 List
的类。
我得到的属性类型如下:
propertyClass = PropertyUtils.getPropertyType(currentObject, property);
我想要做的是检查 propertyClass 是否为 List
> 并获取列表中类型的类对象。之后,我将要创建一个给定类型的 ArrayList 并用该类型的对象填充它(所有这些都是动态创建的,我将使用它从文件动态加载一些数据)。
有没有办法可以使用反射来做到这一点?
I have a class that has a propery List<String>
or List<SomeObject>
.
I get the type of the property as this:
propertyClass = PropertyUtils.getPropertyType(currentObject, property);
What I want to do is check that the propertyClass is a List<SomeType>
and get the class object for the type in the list. After this I will want to create an ArrayList
of the given type and fill it with object of that type (all created dynamically, I will use this to dynamically load some data from a file).
Is there I way I can do this using reflection?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
泛型在编译后会被删除(由于类型删除)。所以你不能在运行时使用它们。
Generics are erased after compilation (due to type erasure). So you can't use them at runtime.
我有类似的问题,而且我实际上找到了适合我的解决方案!
这是可以做到的,但可能不可靠(即它并非在所有情况下都有效)。
首先,您需要获取“字段”(通过反射)。然后获取“GenericType”。然后尝试将其转换为“ParameterizedType”。如果它确实有一个参数,这是可能的。
然后获取“ActualTypeArguments”。通常这些是“Class”,因此您可以对它们进行强制转换(如果不是,您可以尝试 Class.forName(...)),然后您就已经拥有了列表中元素的类型。
但是,如果我这样做,这不起作用:
然后:
您实际上需要检查类型以查看它是否是列表以及它是否具有在任何类或接口中声明的类型。但可能不止一个,并且该类型可以绑定到许多接口,而不仅仅是一个类。
当然,您可以忽略不是“列表”的属性,如果有的话,可能会抛出编译器错误(我可能会这样做)。
然后就是通配符的问题:List list = ...
您所能做的就是将其替换为“Object”,但如果您想将元素添加到列表中,这并不安全! (同样,您可以在编译时进行检查,如果存在通配符则抛出错误)
另一种解决方案是使用已检查的列表(请参阅 Collections.checkedList(List, Class))并尝试在运行时获取该类型(您可能需要对此的反思)。这会比泛型更好、更健壮。
I have a similar problem and I actually found a solution that works for me!
This can be done but it might be unreliable (i.e. it doesn't work in all situations).
First you need to get the "Field" (via reflections). Then get the "GenericType". Then try to cast this to "ParameterizedType". This is possible if it actually has a parameter.
Then get "ActualTypeArguments". Usually those are "Class"es, so you can cast them (if not you could try Class.forName(...)) and then you already have the type of the elements in the list.
However, this doesnt work if I do this:
And then later:
You'd actually need to inspect the type to see if it is a List and if it has a type declared in any class or interface. But there could be more than one and the type could be bound to many interfaces, not just one class.
of course you could just ignore properties that aren't "List" and maybe throw a compiler error if there is one (I'll probably do just that).
Then there is the problem with wildcards: List list = ...
All you can do is substitute it with "Object", but that isn't safe if you want to add elements to the list! (again, you could check that at compile time and throw an error if there are wildcards)
Another solution is to use a checked List (see Collections.checkedList(List, Class)) and try to get that type at runtime (you probably need reflection for that). This would work much better and would be much more robust than just generics.
我找到了 Bob Lee、Sven Mawson 和 Jesse Wilson 的另一个答案:
来源:http:// /google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/reflect/TypeToken.html
甚至还有一个使用的示例
List
它确实有效。TypeToken
将具有rawType
为java.util.List
,并且typeArguments
设置为[java .lang.String]
。这里没有类型擦除!但是,它也不适用于通配符,例如List
。请注意,这与我在其他答案中解释的其他解决方案有点不同。这里您不需要分析 java bean 的属性来获取类型信息。这里您实际上创建了一个存储类型信息的字段。我找不到任何公共构造函数或工厂方法来根据您通过其他方式获得的类型信息创建
TypeToken
。所以我猜它确实只能用作空的匿名内部类。I have found another answer by Bob Lee, Sven Mawson, and Jesse Wilson:
Source: http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/reflect/TypeToken.html
There even is an example using
List<String>
and it really works. TheTypeToken
will have arawType
ofjava.util.List
andtypeArguments
is set to[java.lang.String]
. There is no type erasure here! However it does also not work for wildcards such asList<? extends Foo>
.Note that this is a bit different from the other solution I explained in my other answer. Here you don't analyze a property on a java bean to get the type information. Here you actually create a field that stores the type information. I can't find any public constructor or factory method to create a
TypeToken
from type information that you got some other way. So I guess it really can only be used as an empty anonymous inner class.