Java 获取类的泛型类型从非泛型类型类扩展而来

Java 获取类的泛型类型从非泛型类型类扩展而来,java,generics,Java,Generics,我有一节这样的课 public class RequestDataEditor<T> extends PropertyEditorSupport { @Override public void setAsText(String text) { MyData<T> value; try { //(ParameterizedType)getClass().getGenericSuperclass()

我有一节这样的课

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);
    }
}
当我运行ParameteredTypeGetClass.getGenericSuperclass时, 预期为T,但它是PropertyEditorSupport,不能强制转换为ParameterizedType

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

似乎,我们不能使用ParameteredTypeGetClass.getGenericSuperclass从其父级没有泛型类型的类获取泛型类型

那么,如何使用像RequestDataEditor这样的类来获取泛型类型呢


,我想知道当将ParameterizedTypegetClass.getGenericSuperclass与具有非泛型类型的超类一起使用时有什么不同。

ParameterizedTypegetClass.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);
    }
}
我知道这并不完全是你想要达到的,但这是你能得到的最接近我的知识

当我运行ParameteredTypeGetClass.getGenericSuperclass时, 期望为T,但它是PropertyEditorSupport,不能铸造为 参数化类型

如果您想访问T aka类型参数,那么适当的反射方法是Class.getTypeParameters

请注意,类型参数不是解析为整数,而是解析为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类不是泛型类,而是匿名内部类,由于构造函数后面的{}而扩展了它。。。这是完整类DoubleGeneric的替代方案。。。声明

在这两种选择中,A.和B.更可取,因为一般情况下应避免依赖反射;除此之外,它更容易隐藏运行时错误,并且代码更难维护

我想知道使用时有什么不同 具有类的ParameteredTypeGetClass.getGenericSuperclass已 非泛型类型的超类

如果您查找类型文档,即此方法返回的引用类,则表明它是Java语言中所有可用对象/数据类型的伞形超级接口,甚至包括原语。。。所以对于一个没有泛型超类的类,我猜它会返回一个类型为的子类,反映

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


也许其他人可以给出一个更明智的观点,但我认为这可能有点命名错误。。。我认为getSuperType或类似的东西更合适。也许最初它只支持旧版Java 1.5中的泛型?并最终扩展到其他数据类型,但这只是我的猜测,没有深入研究它的历史

泛型是编译时安全检查。它们在运行时不包含任何可用的类型信息。@4castle但如果类RequestDataEditor没有父类,则我们可以获取泛型类型如果您删除extends PropertyEditorSupport,getGenericSuperclass只返回类对象。请提供一个测试。对不起,我想我犯了一个错误@肯尼特斯。我犯了一个错误。您的回答帮助我对getGenericSuperclass方法有了更深入的理解。感谢您的详细解释!
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".
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