简体   繁体   English

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

[英]Get the generic type of an extending generic class in the constructor of the superclass in Java?

I have an abstract class Abstr<T> and an extending class Ext<T> . 我有一个abstract class Abstr<T>和一个扩展class Ext<T> I need Abstr to know, with which T its extension was initialized so it can return that type. 我需要Abstr知道,扩展名是使用哪个T初始化的,因此它可以返回该类型。 So far I've done this by giving the type to the constructor and then calling the superconstructor to save it. 到目前为止,我已经通过将类型提供给构造函数,然后调用超构造函数进行保存来完成此操作。 But this should work with reflections too I think. 但是我认为这也应该与反思一起起作用。 So far like I said: 到目前为止,就像我说的:

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);
}

Using reflections should rid me of calling any constructor as the extending default constructor will call the abstract classes default constructor which should then save the type of the calling constructor: 使用反射应该让我摆脱调用任何构造函数的麻烦,因为扩展的默认构造函数将调用抽象类的默认构造函数,然后应保存调用构造函数的类型:

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

Thanks! 谢谢!

The only case when it works is when you have a non-generic class with a generic parent. 唯一可行的情况是当您具有带有泛型父级的非泛型类时。 An example would be, 一个例子是

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());
    }
}

For further reading refer to the Reflecting generics tutorial — the answer is there, but it's way too long to quote it and not feel as if I was stealing a code. 要进一步阅读,请参阅Reflecting Generics教程-答案已经存在,但是引用它的时间太长了,感觉好像我在偷代码。 So please read there :) 所以请在那里阅读:)

This might not always work, since if you just have new Ext<String>() in some method there's no reflection data for the type. 这可能并不总是有效,因为如果您在某些方法中仅具有new Ext<String>() ,则该类型将没有反射数据。

Thus Ext<String> ext = new Ext<String>(String.class); 因此Ext<String> ext = new Ext<String>(String.class); would loose the type information at runtime (type erasure) effectively resulting in Ext ext = new Ext(String.class); 将在运行时(类型擦除)有效地释放类型信息,从而导致Ext ext = new Ext(String.class); .

If you have fields like private Ext<String> stringExt or concrete subclasses like StringExt extends Ext<String> you have reflection data you could retrieve. 如果您有private Ext<String> stringExt类的private Ext<String> stringExt或者StringExt extends Ext<String>类的具体子类,则可以获取反射数据。

Here's a short article with some source that you could use to get reflection data for concrete subclasses (and maybe for fields, but I didn't test that): http://www.artima.com/weblogs/viewpost.jsp?thread=208860 这是一篇简短的文章,其中包含一些源代码,可用于获取具体子类(甚至可能用于字段)的反射数据: http : //www.artima.com/weblogs/viewpost.jsp?thread = 208860

As I said, we're using an adjusted version of that code to get type parameters for concrete subclasses. 正如我所说,我们正在使用该代码的调整版本来获取具体子类的类型参数。

So we have something like this: 所以我们有这样的事情:

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

If you really need a method in Abstr similar to 如果您确实需要Abstr类似的方法

public Class<T> getType()

you have no choice but to pass the Class isntance in the constructor (or in any other method). 您别无选择,只能在构造函数(或任何其他方法)中传递Class相等性。 You cannot retrieve the Class of T due to type erasure , which basically comes down to the fact that T is not available at runtime, only at compile time. 由于类型Erase ,您无法检索TClass ,这基本上归结为T在运行时仅在编译时不可用的事实。

The generic type of Abstr is T This all you can get via reflection. Abstr的通用类型为T您可以通过反射获得所有这些。

If you want to simplify your code you can write. 如果您想简化代码,可以编写。

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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM