我有;

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

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


当前回答

简单的回答是:不。

这可能是复制品,现在找不到合适的。

Java使用类型擦除,这意味着在运行时两个对象是等价的。编译器知道列表包含整数或字符串,因此可以维护类型安全的环境。这些信息在运行时丢失(以对象实例为基础),并且列表只包含“对象”。

你可以找到一些关于类的信息,它可能被参数化的类型,但通常这只是任何扩展“对象”的东西,即任何东西。如果将类型定义为

class <A extends MyClass> AClass {....}

class将只包含参数A受MyClass限制的事实,但除此之外,没有办法告诉它。

其他回答

简单的回答是:不。

这可能是复制品,现在找不到合适的。

Java使用类型擦除,这意味着在运行时两个对象是等价的。编译器知道列表包含整数或字符串,因此可以维护类型安全的环境。这些信息在运行时丢失(以对象实例为基础),并且列表只包含“对象”。

你可以找到一些关于类的信息,它可能被参数化的类型,但通常这只是任何扩展“对象”的东西,即任何东西。如果将类型定义为

class <A extends MyClass> AClass {....}

class将只包含参数A受MyClass限制的事实,但除此之外,没有办法告诉它。

如果这些实际上是某个类的字段,那么你可以通过反射来获得它们:

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.
    }
}

对于参数类型和方法的返回类型也可以这样做。

但是如果它们在类/方法的相同范围内,而您需要知道它们,那么就没有必要知道它们,因为您已经自己声明了它们。

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

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检测常规类型。

如果你需要获得一个返回类型的泛型类型,当我需要在一个类中找到一个返回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)((ParameterizedType)field.getGenericType()).getActualTypeArguments()[0]).getSimpleName()