集合的泛型类型只有在它实际上包含对象时才有意义,对吧?那么这样做不是更容易吗:
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 子类的所有项目的列表,然后您可以根据需要对其进行处理。其余项目被过滤到其他列表中。因为它们在地图中,所以您可以根据需要处理它们,或者忽略它们。
如果你想完全忽略其他类的项目,它会变得更简单:
List<Number> numbers = myCollection.stream()
.filter(Number.class::isInstance)
.map(Number.class::cast)
.collect(Collectors.toList());
您甚至可以创建一个实用方法来确保列表仅包含与特定类匹配的那些项目:
public <V> List<V> getTypeSafeItemList(Collection<Object> input, Class<V> cls) {
return input.stream()
.filter(cls::isInstance)
.map(cls::cast)
.collect(Collectors.toList());
}