我有;

List<String> stringList = new ArrayList<String>();
List<Integer> integerList = new ArrayList<Integer>();

是否有(简单)方法检索列表的泛型类型?


当前回答

如果你需要获得一个返回类型的泛型类型,当我需要在一个类中找到一个返回Collection的方法,然后访问它们的泛型类型时,我使用了这种方法:

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;

public class Test {

    public List<String> test() {
        return null;
    }

    public static void main(String[] args) throws Exception {

        for (Method method : Test.class.getMethods()) {
            Class returnClass = method.getReturnType();
            if (Collection.class.isAssignableFrom(returnClass)) {
                Type returnType = method.getGenericReturnType();
                if (returnType instanceof ParameterizedType) {
                    ParameterizedType paramType = (ParameterizedType) returnType;
                    Type[] argTypes = paramType.getActualTypeArguments();
                    if (argTypes.length > 0) {
                        System.out.println("Generic type is " + argTypes[0]);
                    }
                }
            }
        }

    }

}

这个输出:

泛型类型是java.lang.String类

其他回答

我找到了一个非常适合我的答案。

class ArrayListString extends ArrayList<String> {}
class ArrayListInteger extends ArrayList<Integer> {}

ArrayListString als = new ArrayListString();
ArrayListInteger ali = new ArrayListInteger();

void whatType(Object a) {
    if (a instanceof ArrayListString)
        System.out.println("ArrayListString");
    else if (a instanceof ArrayListInteger)
        System.out.println("ArrayListInteger");
}

whatType(als);
whatType(ali);

Als和ali将像它们的泛型一样工作。

这段代码所做的是将泛型类型转换为常规Java类型。在Java中,可以使用instanceof检测常规类型。

在运行时,不可以。

但是,通过反射可以访问类型参数。试一试

for(Field field : this.getDeclaredFields()) {
    System.out.println(field.getGenericType())
}

方法getGenericType()返回一个Type对象。在这种情况下,它将是一个paramtrizedtype的实例,它又有方法getRawType()(在这种情况下,它将包含List.class)和getActualTypeArguments(),它将返回一个数组(在这种情况下,长度为1,包含String.class或Integer.class)。

使用反射来获取这些字段,然后你可以做:Field。genericType来获取包含generic信息的类型。

有同样的问题,但我使用instanceof代替。是这样做的:

List<Object> listCheck = (List<Object>)(Object) stringList;
    if (!listCheck.isEmpty()) {
       if (listCheck.get(0) instanceof String) {
           System.out.println("List type is String");
       }
       if (listCheck.get(0) instanceof Integer) {
           System.out.println("List type is Integer");
       }
    }
}

这涉及到使用未检查的类型转换,所以只有在知道它是一个列表以及它可以是什么类型时才这样做。

一个小的帮助方法:

/**
 * Get type of collection field.
 *
 * @param aClass A class containing collection.
 * @param collectionName A collection field name.
 */
@SneakyThrows
public static Class<?> getCollectionType(Class<?> aClass, String collectionName) {
  Field field = aClass.getDeclaredField(collectionName);
  ParameterizedType genericType = (ParameterizedType) field.getGenericType();
  return (Class<?>) genericType.getActualTypeArguments()[0];
}