我有一个像这样的简单界面。
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.
答案 0 :(得分:1)
1)没有不继承任何类的东西,每个东西都是Object类的扩展,所以即使你没有指定任何东西,默认它也会扩展Object。
2)有两种方法可以在泛型类中获取运行时类型,可以在变量上使用getClass,或者在构造函数或方法中传入类。 示例代码:
方法1(如果可能,首选):
public class MyGenericType<T extends EntityClass>
{
public <T extends EntityClass> void someMethod(final T someVar)
{
Class c = someVar.getClass();
}
}
方法2(如果你需要在施工时确定,这是唯一的方法):
public class MyGenericType<T extends EntityClass>
{
private final Class<? extends EntityClass>genericClazz;
public MyGenericType(Class t)
{
genericClazz = t;
return;
}
}
答案 1 :(得分:1)
由于 erasure ,您无法获取有关泛型类型的信息,简而言之,这意味着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>
课程中的演员阵容的一条评论&#39;构造:
genericClazz = (Class<? extends EntityClass>)...
由于T
声明从EntityClass
延伸,因此您不需要使用通配符。仅使用T
就足够了:
genericClazz = (Class<T>)...
关于您获得的ClassCastException
,因为在您的示例中,MyGenericType
没有通用的超类(实际上,它并没有有Object
之外的任何超类,不是ParameterizedType
。所以,当你使用这个演员:(ParameterizedType) getClass().getGenericSuperclass()
时,你得到ClassCastException
。< / p>
修改强>
我忘了你问的是如何做到这一点没有必须从任何课程扩展。一种方法是在构造函数中传递泛型类型:
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
}
}