繁体   English   中英

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

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

我有这样的课

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

当我运行(ParameterizedType)getClass().getGenericSuperclass() ,期望是T,但是它是PropertyEditorSupport,并且不能转换为ParameterizedType。

如果我删除extends PropertyEditorSupport ,那么我可以得到泛型类型(证明是错误的,我在这里犯了一个错误)。

看来,我们不能使用(ParameterizedType)getClass().getGenericSuperclass()从其父级没有泛型类型的类中获取泛型类型。

那么,如何使用诸如RequestDataEditor之类的类来获取泛型呢?

与问题不重复 ,我想知道将(ParameterizedType)getClass().getGenericSuperclass()与一个类一起使用时,有一个非泛型类型超类时有什么区别。

(ParameterizedType)getClass()。getGenericSuperclass()将获取您当前类的超类,该超类不是通用类。 您需要当前类的通用类型,而不是其超类。 在您的示例中,这将是不可能的,因为在运行时该数据不再可用。 可能的解决方案可能是:

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

我知道这并不是您要尝试实现的目标,但是(据我所知)这是您可以获得的最接近的目标。

当我运行(ParameterizedType)getClass()。getGenericSuperclass()时,期望它是T,但它是PropertyEditorSupport,并且不能转换为ParameterizedType。

如果你想有机会获得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]);
  }
}

如果运行上面的代码,则会得到以下信息:

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

注意,由于此信息在运行时不可用,因此类型参数不是解析为Integer而是解析为T

如果访问此信息对您很重要,那么您有两个简单的选择。

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.创建一个子类,为该类型参数提供一个具体的类:

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

注意,gint4类不是Generic<Double>而是在匿名内部类中由于构造函数后面的{}而对其进行了扩展。这是完整class DoubleGeneric ...声明的替代方法。

在A.和B.这两种选择中,A。是可取的,因为通常应避免依赖反射。 除其他外,更容易隐藏运行时错误,并且代码更难以维护。

我想知道将(ParameterizedType)getClass()。getGenericSuperclass()与一个类一起使用时,有一个非泛型类型超类时有什么区别。

如果您查找Type文档(此方法返回的引用的类),则表明它是Java语言中可用的所有对象/数据类型(甚至包括基元)的“伞形”超级接口。一个没有通用超类的类,我想它将返回一个反映该类型的子类...

一个快速的实验表明,实际上它将返回一个“ Class”对象,因此它等效于getSuperclass()。

也许其他人可以对此提供更详尽的见解,但是我认为这可能有点误名……我认为getSuperType()或类似的东西会更合适。 也许最初它仅支持较旧的Java版本(1.5?)中的泛型,最终被扩展为涵盖其他数据类型,但这是我的一个大胆猜测,而无需研究其历史。

暂无
暂无

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

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