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