如何在Java泛型中获取类型变量的类

ZeD*_*ino 20 java generics types type-erasure

我见过类似的问题,但他们没有多大帮助.

例如,我有这个通用类:

public class ContainerTest<T>
{

    public void doSomething()
    {
        //I want here to determinate the Class of the type argument (In this case String)
    }
}
Run Code Online (Sandbox Code Playgroud)

和另一个使用此容器类的类

public class TestCase
{

    private ContainerTest<String> containerTest;

    public void someMethod()
    {
        containerTest.doSomething();
    }
}
Run Code Online (Sandbox Code Playgroud)

是否有可能在方法doSomething()中确定类型参数的类而没有在ContainerTest类中使用显式类型变量/字段或任何构造函数

更新:更改ContainerTest类的格式

Did*_*r L 13

唯一的方法是将类存储在实例变量中,并将其作为构造函数的参数:

public class ContainerTest<T>
{
    private Class<T> tClass;
    public ContainerTest(Class<T> tClass) {
        this.tCLass = tClass;
    }

    public void doSomething()
    {
        //access tClass here
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你确定这是唯一的方法吗? (2认同)

ded*_*dek 10

如果您对反射方式感兴趣,我在这篇很棒的文章中找到了部分解决方案:http: //www.artima.com/weblogs/viewpost.jsp?thread = 208860

简而言之,您可以使用java.lang.Class.getGenericSuperclass()java.lang.reflect.ParameterizedType.getActualTypeArguments()方法,但您必须子类化一些父超类.

以下代码段适用于直接扩展超类的类AbstractUserType.有关更一般的解决方案,请参阅参考文章

import java.lang.reflect.ParameterizedType;


public class AbstractUserType<T> {

    public Class<T> returnedClass() {
        ParameterizedType parameterizedType = (ParameterizedType) getClass()
                .getGenericSuperclass();

        @SuppressWarnings("unchecked")
        Class<T> ret = (Class<T>) parameterizedType.getActualTypeArguments()[0];

        return ret;
    }

    public static void main(String[] args) {
        AbstractUserType<String> myVar = new AbstractUserType<String>() {};

        System.err.println(myVar.returnedClass());
    }

}
Run Code Online (Sandbox Code Playgroud)


Ren*_*aud 5

从类中获取Generic Type参数没有"干净"的方法.相反,常见的模式是将通用类的类传递给构造函数,并将其作为内部属性juste保存,如java.util.EnumMap实现中所做的那样.

http://docs.oracle.com/javase/1.5.0/docs/api/java/util/EnumMap.html http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk /6-b14/java/util/EnumMap.java

public class ContainerTest<T> {

    Class<T> type;
    T t;

    public ContainerTest(Class<T> type) {
        this.type = type;
    }

    public void setT(T t) {
        this.t = t;
    }

    public T getT() {
        return t;
    }

    public void doSomething() {
        //There you can use "type" property.
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @ZeDonDino 我链接 EnumMap 以表明即使 OpenJDK 也在标准实现中使用这种模式。 (2认同)

Jav*_*ier 5

不。由于类型擦除,这是不可能的(类型参数被编译为 Object + 类型转换)。如果您确实需要在运行时了解/强制执行该类型,您可以存储对对象的引用Class

public class ContainerTest<T> {
   private final Class<T> klass;
   private final List<T> list = new ArrayList<T>();

   ContainerTest(Class<T> klass) {
     this.klass = klass;
   }

   Class<T> getElementClass() {
     return klass;
   }

   void add(T t) {
      //klass.cast forces a runtime cast operation
      list.add(klass.cast(t));
   }
}
Run Code Online (Sandbox Code Playgroud)

使用:

ContainerTest<String> c = new ContainerTest<>(String.class);
Run Code Online (Sandbox Code Playgroud)

  • 请谨慎使用,仅 Java SE 7 及更高版本支持此功能。 (2认同)