我有一个像这样的简单界面。
public interface EntityClass
{
public void setId(final Integer id);
public Integer getId();
}
和一堂课
public Student implements EntityClass{}
但是这段代码给了我我想知道
Generic Type
的错误public class MyGenericType<T extends EntityClass>
{
private final Class<? extends EntityClass>genericClazz;
public MyGenericType()
{
genericClazz=(Class<? extends EntityClass>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
return;
}
}
后来我尝试这样的代码
public static void main(String[] args)
{
final MyGenericType<Student>action = new MyGenericType<>();
}
但是它抛出
Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType
这段代码我一直在使用,但是从子类扩展而来,但是我不想从任何类扩展到我的
GenericType
。我该怎么做才能从此代码中获取
Student
类型。final MyGenericType<Student>action = new MyGenericType<>();
因为我需要得到一个
Hibernate namedQuery.
最佳答案
由于擦除,您无法获取有关泛型类型的信息,这简而言之,这意味着Java编译器不会在生成的字节码中保留有关实际实例的泛型类型信息。
但是,编译器不会删除实际实例超类的泛型类型信息。因此,您可以在具有通用类型参数的类的后代上使用(ParameterizedType) this.getClass().getGenericSuperclass()
,为此,您需要使用extends
关键字:
public interface EntityClass {
public void setId(final Integer id);
public Integer getId();
}
public class Student
implements EntityClass {
// getters and setters
}
public abstract class MyGenericType<T extends EntityClass> {
private final Class<T> genericClazz;
@SuppressWarnings("unchecked")
public MyGenericType() {
this.genericClazz = (Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
protected Class<T> getGenericClazz() {
return this.genericClazz;
}
}
public class MyStudentType // no way to avoid extending a generic type
extends MyGenericType<Student> {
@Override
public String toString() {
return this.getGenericClazz().getSimpleName();
}
}
public class Sample {
public static void main(String[] args) {
final MyStudentType action = new MyStudentType();
System.out.println(action); // Student
}
}
关于
MyGenericType<T>
类的构造函数中的此强制转换的一条评论:genericClazz = (Class<? extends EntityClass>)...
由于声明了
T
从EntityClass
扩展,因此您不需要使用通配符。仅使用T
就足够了:genericClazz = (Class<T>)...
关于您获得的
ClassCastException
,这是因为在您的示例中,MyGenericType
没有通用的超类(实际上,除了Object
之外它没有任何超类,它不是ParameterizedType
因此,当您使用以下强制转换:(ParameterizedType) getClass().getGenericSuperclass()
时,会得到一个ClassCastException
。编辑:
我忘记了您在问如何做到这一点,而不必从任何课程扩展。一种方法是在构造函数中传递泛型类型:
public class MyGenericType<T extends EntityClass> {
private final Class<T> genericClazz;
public MyGenericType(Class<T> clazz) {
this.genericClazz = clazz;
}
@Override
public String toString() {
return this.genericClazz.getSimpleName();
}
}
然后:
public class Sample {
public static void main(String[] args) {
final MyGenericType<Student> action = new MyGenericType<>(Student.class);
System.out.println(action); // Student
}
}
编辑2:
另一种方法是使您的
MyGenericType
类abstract
并使子类返回通用类型。这可能是由泛型强制执行的,因此,如果子类尝试返回错误的类型,则会得到编译错误:public abstract class MyGenericType<T extends EntityClass> {
protected abstract Class<T> getGenericType();
@Override
public String toString() {
return this.getGenericType().getSimpleName();
}
}
public class MyStudentType
extends MyGenericType<Student> {
@Override
protected Class<Student> getGenericType() {
return Student.class;
}
}
然后:
public class Sample {
public static void main(String[] args) {
final MyStudentType action = new MyStudentType();
System.out.println(action); // Student
}
}