我有一个像这样的简单界面。

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>)...


由于声明了TEntityClass扩展,因此您不需要使用通配符。仅使用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:

另一种方法是使您的MyGenericTypeabstract并使子类返回通用类型。这可能是由泛型强制执行的,因此,如果子类尝试返回错误的类型,则会得到编译错误:

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
    }
}

10-02 05:20
查看更多