简体   繁体   English

获取类的泛型类型从无泛型类型类扩展

[英]Get generic type of a class extends from a none generic type class

I have a class like this 我有这样的课

public class RequestDataEditor<T> extends PropertyEditorSupport {
    @Override
    public void setAsText(String text) {

        MyData<T> value;

        try {
            //(ParameterizedType)getClass().getGenericSuperclass()

            value = JacksonUtil.parse(text, new TypeReference<MyData<T>>() {
            });
        } catch (Exception e) {
            value = null;
        }

        setValue(value);
    }
}

When I run (ParameterizedType)getClass().getGenericSuperclass() , expect to be T, but it's PropertyEditorSupport, and can't be casted to ParameterizedType; 当我运行(ParameterizedType)getClass().getGenericSuperclass() ,期望是T,但是它是PropertyEditorSupport,并且不能转换为ParameterizedType。

If i remove the extends PropertyEditorSupport , then i can get the generic type.(Proved to be wrong, i made a mistake here.) 如果我删除extends PropertyEditorSupport ,那么我可以得到泛型类型(证明是错误的,我在这里犯了一个错误)。

It seems that, we can't use (ParameterizedType)getClass().getGenericSuperclass() to get generic type from a class whose parent has no generic type. 看来,我们不能使用(ParameterizedType)getClass().getGenericSuperclass()从其父级没有泛型类型的类中获取泛型类型。

So how can I get the generic type with such a class like RequestDataEditor? 那么,如何使用诸如RequestDataEditor之类的类来获取泛型呢?

not duplicate with the question , I want to know what's the different when use (ParameterizedType)getClass().getGenericSuperclass() with a class has a none generic type super class. 与问题不重复 ,我想知道将(ParameterizedType)getClass().getGenericSuperclass()与一个类一起使用时,有一个非泛型类型超类时有什么区别。

The (ParameterizedType)getClass().getGenericSuperclass() will get the super class of your current class which is not a generic one. (ParameterizedType)getClass()。getGenericSuperclass()将获取您当前类的超类,该超类不是通用类。 You want the generic type of the current class and not its super class. 您需要当前类的通用类型,而不是其超类。 In your example this will be impossible because this data is no longer available at run time. 在您的示例中,这将是不可能的,因为在运行时该数据不再可用。 A possible solution could be: 可能的解决方案可能是:

public class RequestDataEditor<T> extends PropertyEditorSupport {

    private final Class<T> genericType;

    public RequestDataEditor(Class<T> genericType) {
        this.genericType = genericType;
    }

    @Override
    public void setAsText(String text,  ) {

        MyData<T> value;

        try {
            //use genericType here

            value = JacksonUtil.parse(text, new TypeReference<MyData<T>>() {
            });
        } catch (Exception e) {
            value = null;
        }

        setValue(value);
    }
}

I know this isn't exactly what you try to achieve but it's the closest you can get (to my knowledge). 我知道这并不是您要尝试实现的目标,但是(据我所知)这是您可以获得的最接近的目标。

When I run (ParameterizedType)getClass().getGenericSuperclass(), expect to be T, but it's PropertyEditorSupport, and can't be casted to ParameterizedType; 当我运行(ParameterizedType)getClass()。getGenericSuperclass()时,期望它是T,但它是PropertyEditorSupport,并且不能转换为ParameterizedType。

If you want to have access to the T aka the type-parameter, the appropriate reflection method is Class.getTypeParameters . 如果你想有机会获得T又名类型参数,适当的反射法是Class.getTypeParameters

// Test.java:
class Generic<T> {
}

class Main {

  public static void main(String[] args) {

     final Generic<Integer> gint1 = new Generic<Integer>();

     System.err.println("gint1's type-parameter: " 
                       + gint1.getClass().getTypeParameters()[0]);
  }
}

If you run the code above you get the following: 如果运行上面的代码,则会得到以下信息:

$ javac Test.java
$ java Main
gint1's type-parameter: T

Notice that the type parameter is not resolved as Integer but as T since this information in not available at run-time. 注意,由于此信息在运行时不可用,因此类型参数不是解析为Integer而是解析为T

If access to this information is important for you, then you have two straight forward options. 如果访问此信息对您很重要,那么您有两个简单的选择。

A. the object contains a reference to the actual type class: A.对象包含对实际类型类的引用:

class Generic<T> {

    public final Class<T> type;

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

    public Class<T> type() {
        return type;
    }
}

class Main {
    public static void main(String[] args) {

        final Generic<Integer> gint2 = new Generic<>(Integer.class);
        System.err.println("gint2's type-parameter: " + gint2.type().getSimpleName());
    }
}
// Output will be "gint2's type-parameter: Integer".

B. You create a subclass that gives a concrete class for that type-parameter: B.创建一个子类,为该类型参数提供一个具体的类:

import java.lang.reflect.*;

class Generic<T> {
}

class IntegerGeneric extends Generic<Integer> {
}

class Main {
    public static void main(String[] args) {

        final Generic<Integer> gint3 = new IntegerGeneric();
        final Generic<Double> gint4 = new Generic<Double>() {};
        System.err.println("gint3's type-parameter: "
            + ((ParameterizedType)gint3.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
        System.err.println("gint4's type-parameter: "
            + ((ParameterizedType)gint4.getClass().getGenericSuperclass()).getActualTypeArguments()[0]);
    }
}
// Output:
// gint3's type-parameter: class java.lang.Integer
// gint4's type-parameter: class java.lang.Double

Notice that gint4 class is not Generic<Double> but at anonymous inner class that extends it due to the {} following the constructor... this is an alternative to a full class DoubleGeneric ... declaration. 注意,gint4类不是Generic<Double>而是在匿名内部类中由于构造函数后面的{}而对其进行了扩展。这是完整class DoubleGeneric ...声明的替代方法。

Of these two alternatives, A. and B., A. is preferable as in general one should avoid to rely on reflection; 在A.和B.这两种选择中,A。是可取的,因为通常应避免依赖反射。 amongst other things it is more prone to hide run-time errors and the code is more difficult to maintain. 除其他外,更容易隐藏运行时错误,并且代码更难以维护。

I want to know what's the different when use (ParameterizedType)getClass().getGenericSuperclass() with a class has a none generic type super class. 我想知道将(ParameterizedType)getClass()。getGenericSuperclass()与一个类一起使用时,有一个非泛型类型超类时有什么区别。

If you look-up the Type documentation, the class of the reference returned by this methods, it indicates that it is an "umbrella" super-interface for all object/data types available in the Java language including even primitives ... so for a class that does not have a generic superclass I guess it would return a subclass of type that reflect that... 如果您查找Type文档(此方法返回的引用的类),则表明它是Java语言中可用的所有对象/数据类型(甚至包括基元)的“伞形”超级接口。一个没有通用超类的类,我想它将返回一个反映该类型的子类...

A quick experiment reveals that in fact it would return a 'Class' object so it would be equivalent to to getSuperclass(). 一个快速的实验表明,实际上它将返回一个“ Class”对象,因此它等效于getSuperclass()。

Perhaps others can give a more informed perspective on this, but I think this might have been a bit of a misnaming ... I think getSuperType() or something like that would have been more appropriate. 也许其他人可以对此提供更详尽的见解,但是我认为这可能有点误名……我认为getSuperType()或类似的东西会更合适。 Perhaps initially it only supported generics in an older Java version (1.5?) and eventually was extended to cover other data types but this is a wild guess of mine without looking into its history. 也许最初它仅支持较旧的Java版本(1.5?)中的泛型,最终被扩展为涵盖其他数据类型,但这是我的一个大胆猜测,而无需研究其历史。

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

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