在Java中的超类的构造函数中获取泛型泛型类的泛型类型?

时间:2012-01-10 10:30:39

标签: java generics reflection

我有一个abstract class Abstr<T>和一个class Ext<T>。我需要Abstr知道,T其扩展名已初始化,因此可以返回该类型。到目前为止,我已经通过将类型赋予构造函数然后调用超级构造函数来保存它来完成此操作。但我认为这也应该与反思一起使用。到目前为止,就像我说的那样:

public abstract class Abstr<T> {

    private Class<T> type;

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

}

public class Ext<T> extends Abstr<T> {

    public Ext(Class<T> _class) {
        super(_class);
    }

}

public void someMethod() {
    Ext<String> ext = new Ext<String>(String.class);
}

使用反射应该不再调用任何构造函数,因为扩展的默认构造函数将调用抽象类的默认构造函数,然后应该保存调用构造函数的类型:

public Abstr() {    
    this.type = (Class<D>) this.getClass().getTheTypeParameter(); // something along these lines
}

谢谢!

4 个答案:

答案 0 :(得分:3)

唯一可行的情况是你有一个带有通用父级的非泛型类。一个例子是,

class Trick<T> {
    T t;
}

public class GenericTest {
    public static void main(String[] args) {
        Trick<Set<String>> trick = new Trick<Set<String>>() {
        };

        // Prints "class org.acm.afilippov.GenericTest$1"
        System.out.println(trick.getClass());
        // Prints "org.acm.afilippov.Trick<java.util.Set<java.lang.String>>"
        System.out.println(trick.getClass().getGenericSuperclass());
    }
}

有关进一步阅读,请参阅Reflecting generics教程 - 答案就在那里,但引用它并且感觉不像是在窃取代码时感觉太长了。所以请在那里阅读:)

答案 1 :(得分:1)

这可能并不总是有效,因为如果你在某种方法中只有new Ext<String>(),则该类型没有反射数据。

因此Ext<String> ext = new Ext<String>(String.class);会在运行时松散类型信息(类型擦除),从而导致Ext ext = new Ext(String.class);

如果您有private Ext<String> stringExt之类的字段或像StringExt extends Ext<String>这样的具体子类,则可以检索反射数据。

这是一篇简短的文章,其中包含一些可用于获取具体子类的反射数据的源文章(可能用于字段,但我没有对其进行测试):http://www.artima.com/weblogs/viewpost.jsp?thread=208860

正如我所说,我们正在使用该代码的调整版本来获取具体子类的类型参数。

所以我们有这样的事情:

class AbstractDAO<T entityType> {
  protected Class<?> entityClass;

  protected AbstractDAO() {
    //ReflectionUtil is our adjusted version of code in the link above
    entityClass = ReflectionUtil.getTypeArguments(AbstractDAO.class, getClass() ).get(0);
  }
}

//Here entityClass is User.class
class UserDAO extends AbstractDAO<User> { ... }

答案 2 :(得分:1)

如果您真的需要Abstr中类似于

的方法
public Class<T> getType()

你别无选择,只能在构造函数(或任何其他方法)中传递Class isntance。由于type erasure,您无法检索Class T,这基本上归结为T在运行时不可用,仅在编译时。

答案 3 :(得分:1)

Abstr的泛型类型是T这可以通过反射获得。

如果您想简化代码,可以编写。

public class Ext<T> extends Abstr<T> {
    protected Ext(Class<T> _class) {
        super(_class);
    }

    public static <T> Ext<T> of(Class<T> _class) { return new Exit<T>(_class); }
}

Ext<String> ext = Ext.of(String.class);