英文:
How to get a class of a generic in a superclass?
问题
以下是您提供的内容的翻译部分:
/**
* 空类
*/
private static class Foo{}
/**
* 非泛型类,继承自泛型类
*/
private static class ChildA extends GenericClass<Foo>{}
/**
* 泛型类,继承自泛型类
*/
private static class ClassChildB<T> extends GenericClass<T>{}
private abstract static class GenericClass<T> {
@SuppressWarnings("unchecked")
public GenericClass() {
Type type = getClass().getGenericSuperclass();
/**
* 当从ChildA构造时:
* type = generics.Main$GenericClass<generics.Main$Foo>
* 在其他词中是泛型类型
*
* 但是当从GenericChildB构造时:
* 泛型类型只是:
* type = generics.Main$GenericClass<T>
* 并且当尝试将其转换为ParameterizedType时会引发错误
* 因为<T>不是一个实际的类。
*
*/
System.out.println(type);
Class<T> classInstance = (Class<T>) ((ParameterizedType)type).getActualTypeArguments()[0];
// 目标是在GenericClass的构造函数中获取一个Class<T>对象
System.out.println(classInstance);
}
}
public static void main(String[] args) {
// 正常工作:
GenericClass<Foo> genericClassA = new ChildA();
// 不起作用:
GenericClass<Foo> genericClassB = new GenericChildB<Foo>();
}
注意:在代码的翻译中,我保留了原始的类名和注释,只将其翻译成中文。
英文:
How do I get a class of the generic type inside of the super class constructor?
In other words I want a Class<T>
instance where T is the generic from my super class.
This would work in the code below for the ChildA
class where I define the generic class directly in the class itself, but I also need it to work when the child class is a generic class like in the example with GenericChildB
.
/**
* empty class
*/
private static class Foo{}
/**
* non generic class that extends from a generic class
*/
private static class ChildA extends GenericClass<Foo>{}
/**
* generic class that extends from a generic class
*/
private static class ClassChildB<T> extends GenericClass<T>{}
private abstract static class GenericClass<T> {
@SuppressWarnings("unchecked")
public GenericClass() {
Type type = getClass().getGenericSuperclass();
/**
* When constructed from ChildA:
* type = generics.Main$GenericClass<generics.Main$Foo>
* with other worlds the generic type
*
* But when constructed from GenericChildB:
* the generic type is just:
* type = generics.Main$GenericClass<T>
* and it throws an error when trying to cast his to an ParameterizedType
* because <T> is not an acctual class.
*
*/
System.out.println(type);
Class<T> classInstance = (Class<T>) ((ParameterizedType)type).getActualTypeArguments()[0];
//Goal is to get an Class<T> object inside of the constructor of GenericClass
System.out.println(classInstance);
}
}
public static void main(String[] args) {
//works :
GenericClass<Foo> genericClassA = new ChildA();
//does not work:
GenericClass<Foo> genericClassB = new GenericChildB<Foo>();
}
答案1
得分: 1
这是因为在Java中存在类型擦除。
在第一种情况下,您将非泛型类ChildA
与GenericClass
的具体实现即GenericClass<Foo>
在编译时绑定在一起。因此,Java能够使用这些信息。
在第二种情况下,GenericChildB
与Foo
之间的绑定仅在运行时发生。Java不能使用这些信息。
按照以下方式扩展您的示例:
private static class ClassChildC extends ClassChildB<Foo>{}
因为这个类是非泛型的,绑定在编译时发生。您将能够再次获取类型信息。
这可能在您的实际情况下是可接受的,但这几乎是保留Java类型擦除中的类型信息的唯一方法。
英文:
This happens because of type erasure in Java.
In the first case, you bind the non-generic class ChildA
with a concrete implementation of GenericClass
i.e. GenericClass<Foo>
at compile-time. So Java is able to use this information.
In the second case, the binding between GenericChildB
and Foo
only happens at run-time. Java is not able to use this information.
Extend your example this way:
private static class ClassChildC extends ClassChildB<Foo>{}
Because this class is non-generic, the binding happens at compile-time. You will be able to get type information again.
This may or may not be acceptable in your real scenario, but it's pretty much the only way to retain type information with Java type erasure.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论