本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看<活动链接>
提问:如何获取java.util.List的通用类型 ?
List<String> stringList = new ArrayList<String>();
List<Integer> integerList = new ArrayList<Integer>();
有没有一种(简单的)方法来检索列表的通用类型?、
回答1:
如果这些实际上是某个类的字段,那么您可以在反射的帮助下获得它们:
package test;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
public class Test {
List<String> stringList = new ArrayList<String>();
List<Integer> integerList = new ArrayList<Integer>();
public static void main(String... args) throws Exception {
Field stringListField = Test.class.getDeclaredField("stringList");
ParameterizedType stringListType = (ParameterizedType) stringListField.getGenericType();
Class<?> stringListClass = (Class<?>) stringListType.getActualTypeArguments()[0];
System.out.println(stringListClass); // class java.lang.String.
Field integerListField = Test.class.getDeclaredField("integerList");
ParameterizedType integerListType = (ParameterizedType) integerListField.getGenericType();
Class<?> integerListClass = (Class<?>) integerListType.getActualTypeArguments()[0];
System.out.println(integerListClass); // class java.lang.Integer.
}
}
您还可以对参数类型和方法的返回类型执行此操作。
回答2:
您也可以对方法参数执行相同的操作:
Method method = someClass.getDeclaredMethod("someMethod");
Type[] types = method.getGenericParameterTypes();
//Now assuming that the first parameter to the method is of type List<Integer>
ParameterizedType pType = (ParameterizedType) types[0];
Class<?> clazz = (Class<?>) pType.getActualTypeArguments()[0];
System.out.println(clazz); //prints out java.lang.Integer
回答3:
集合的泛型类型仅在实际上包含对象的情况下才重要,对吧?因此,这样做不是更容易吗?
Collection<?> myCollection = getUnknownCollectionFromSomewhere();
Class genericClass = null;
Iterator it = myCollection.iterator();
if (it.hasNext()){
genericClass = it.next().getClass();
}
if (genericClass != null) { //do whatever we needed to know the type for
在运行时没有泛型类型,但是保证运行时内部的对象与声明的泛型类型相同,因此在处理项目之前测试项目的类就足够容易了。
您可以做的另一件事就是简单地处理列表以获取正确类型的成员,而忽略其他成员(或以不同方式处理它们)。
Map<Class<?>, List<Object>> classObjectMap = myCollection.stream()
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(Object::getClass));
// Process the list of the correct class, and/or handle objects of incorrect
// class (throw exceptions, etc). You may need to group subclasses by
// filtering the keys. For instance:
List<Number> numbers = classObjectMap.entrySet().stream()
.filter(e->Number.class.isAssignableFrom(e.getKey()))
.flatMap(e->e.getValue().stream())
.map(Number.class::cast)
.collect(Collectors.toList());
这将为您提供所有项目的列表,这些项目的类是子类Number,您可以根据需要对其进行处理。其余项目被过滤到其他列表中。因为它们在map,所以您可以根据需要对其进行处理,也可以将其忽略。