简体   繁体   English

通用列表属性,获取通用类型

[英]Generic List property, get type of generic

I have a class that has a propery List<String> or List<SomeObject> . 我有一个具有适当的List<String>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. 我要做的是检查propertyClass是否为List<SomeType>并获取列表中类型的类对象。 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). 之后,我将要创建给定类型的ArrayList并用该类型的对象填充它(所有对象都是动态创建的,我将使用它来动态加载文件中的某些数据)。

Is there I way I can do this using reflection? 我可以用反射方式做到这一点吗?

Generics are erased after compilation (due to type erasure ). 编译后,泛型将被擦除(由于类型Erase )。 So you can't use them at runtime. 因此,您不能在运行时使用它们。

I have a similar problem and I actually found a solution that works for me! 我有一个类似的问题,实际上我找到了适合我的解决方案!

This can be done but it might be unreliable (ie it doesn't work in all situations). 可以这样做,但是可能不可靠(即,并非在所有情况下都有效)。 First you need to get the "Field" (via reflections). 首先,您需要获取“字段”(通过反射)。 Then get the "GenericType". 然后获取“ GenericType”。 Then try to cast this to "ParameterizedType". 然后尝试将其强制转换为“ ParameterizedType”。 This is possible if it actually has a parameter. 如果它实际上有一个参数,这是可能的。 Then get "ActualTypeArguments". 然后获取“ 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. 通常这些是“类”,因此您可以将其强制转换(如果不能,则可以尝试Class.forName(...)),然后您已经具有列表中元素的类型。

However, this doesnt work if I do this: 但是,如果执行此操作,则不起作用:

class MyList extends List<String> {... }

And then later: 然后再:

MyList list = new MyList(); // This would be List<String>

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. 实际上,您实际上需要检查类型,以查看它是否为List,以及是否在任何类或接口中声明了类型。 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). 当然,您可以忽略那些不是“ List”的属性,如果有的话可能会引发编译器错误(我可能会这样做)。

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). 另一个解决方案是使用检查列表(请参见Collections.checkedList(List,Class)),并尝试在运行时获取该类型(您可能需要反射)。 This would work much better and would be much more robust than just generics. 这将比泛型更好,更健壮。

I have found another answer by Bob Lee, Sven Mawson, and Jesse Wilson: 我找到了鲍勃·李,斯文·莫森和杰西·威尔逊的另一个答案:

[public class TypeToken:] Represents a generic type T. Java doesn't yet provide a way to represent generic types, so this class does. [公共类TypeToken:]表示通用类型T。Java尚未提供表示通用类型的方法,因此此类可以。 Forces clients to create a subclass of this class which enables retrieval the type information even at runtime. 强制客户端创建此类的子类,即使在运行时也可以检索类型信息。

Source: http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/com/google/gson/reflect/TypeToken.html 来源: 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. 甚至有一个使用List<String>的示例,它确实有效。 The TypeToken will have a rawType of java.util.List and typeArguments is set to [java.lang.String] . TypeTokenrawTypejava.util.List并且typeArguments设置为[java.lang.String] There is no type erasure here! 这里没有类型擦除! However it does also not work for wildcards such as List<? extends Foo> 但是,它对于诸如List<? extends Foo>这样的通配符也不起作用List<? extends Foo> List<? extends Foo> . List<? 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. 在这里,您无需分析Java Bean上的属性即可获取类型信息。 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. 我找不到任何公共构造函数或工厂方法来通过其他方式从类型信息创建TypeToken So I guess it really can only be used as an empty anonymous inner class. 所以我想它真的只能用作一个空的匿名内部类。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM