6.8 如何获取java.util.List的通用类型 ?| Java Debug 笔记

259 阅读2分钟

本文正在参加「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,所以您可以根据需要对其进行处理,也可以将其忽略。