在 Java 中获取列表中的泛型类型
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4155252/
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
Get type of generic type inside a List in Java
提问by Phu Nguyen
I have the below function:
我有以下功能:
public <T> void putList(String key, List<T> lst){
if (T instanceof String) {
// Do something
}
if (T instanceof Integer) {
// Do something
}
}
Inside this function, i want to know if <T> is String or Integer so i wonder if there is a way to discover its type? I used the above code but it generated error
在这个函数中,我想知道 <T> 是 String 还是 Integer 所以我想知道是否有办法发现它的类型?我使用了上面的代码,但它产生了错误
Thank you in advance.
先感谢您。
回答by Teja Kantamneni
回答by Brad Cupit
It's not possible in Java due to erasure. What most people do instead is add a type token. Example:
由于擦除,在 Java 中这是不可能的。大多数人做的是添加一个类型标记。例子:
public <T> void putList(String key, List<T> list, Class<T> listElementType) {
}
There are certain situations where reflection can get at the type parameter, but it's for cases where you've pre-set the type parameter. For example:
在某些情况下,反射可以获取类型参数,但适用于您预先设置类型参数的情况。例如:
public class MyList extends List<String> {
private List<String> myField;
}
In both of those cases reflection can determine the List is of type String, but reflection can't determine it for your case. You'd have to use a different approach like a type token.
在这两种情况下,反射都可以确定 List 是 String 类型,但反射无法确定它是否适合您的情况。您必须使用不同的方法,例如类型标记。
回答by DJClayworth
It is not possible to determine this due to erasure, which means that the parameter is not stored in the code. However you can either pass an extra parameter specifying what type the list is:
由于擦除,无法确定这一点,这意味着该参数未存储在代码中。但是,您可以传递一个额外的参数来指定列表的类型:
public <T> void putList(String key, List<T> lst, Class<T> listElementType) {
}
}
or you can determine the type of each element at runtime:
或者您可以在运行时确定每个元素的类型:
public <T> void putList(String key, List<T> lst){
for (Object elem:lst) {
if (elem instanceof String) {
// Do something
}
if (elem instanceof Integer) {
// Do something
}
}
}
回答by AlexR
Generics are called "erasures" because they exist at compile time only and are removed by compiler. So, there is no way to determine the generic type of collection. The only way to do it for non-empty lists is to take the first element and determine its type.
泛型被称为“擦除”,因为它们仅在编译时存在并被编译器删除。因此,无法确定集合的泛型类型。对非空列表执行此操作的唯一方法是获取第一个元素并确定其类型。
This is almost the same solution that was suggested by DJClayworth, but I think that there is no need to check each element of the list. If you are sure that the list is created with generics (new ArrayList() or new LinkedList() etc) all its element are guaranteed to be of the same type.
这几乎与 DJClayworth 建议的解决方案相同,但我认为没有必要检查列表的每个元素。如果您确定列表是使用泛型(new ArrayList() 或 new LinkedList() 等)创建的,则它的所有元素都保证为相同类型。
回答by MCS97
If you want to run function of the object, you can do:
如果要运行对象的功能,可以执行以下操作:
public <T> void putList(String key, List<T> lst){
for(T object : lst){
if(object instanceof String) {
doSomething(((String)object).doForString())
}
if(object instanceof Integer) {
doSomething(((Integer)object).doForInteger())
}
}
}
回答by PaulJWilliams
Use the instanceof operator.
使用 instanceof 运算符。
That said, generic operations should be, well, generic, so be wary of changing behaviour based on type.
也就是说,泛型操作应该是泛型的,所以要警惕基于类型改变行为。
回答by Neil
Type genericType = lst.getType();
if(genericType instanceof ParameterizedType){
ParameterizedType aType = (ParameterizedType) genericType;
Type[] fieldArgTypes = aType.getActualTypeArguments();
for(Type fieldArgType : fieldArgTypes){
Class fieldArgClass = (Class) fieldArgType;
System.out.println("fieldArgClass = " + fieldArgClass);
}
}