Java 获取没有扩展的通用类型
Java Get Generic Type without extends
我有一个像这样的简单界面。
public interface EntityClass
{
public void setId(final Integer id);
public Integer getId();
}
和一个class
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
这段代码我一直在使用它但是从 subclass 扩展但我不想我的 GenericType
从任何 class.
扩展
我该怎么做才能从此代码中获取 Student
类型。
final MyGenericType<Student>action = new MyGenericType<>();
因为我需要得到一个Hibernate namedQuery.
1) 没有不继承任何class的东西,每一样东西都是对象class的扩展,所以即使你不指定任何东西,默认情况下它将扩展对象。
2) 在泛型class中有两种获取运行时类型的方法,可以在变量上使用getClass,或者在构造函数或方法中传入class。
示例代码:
方法一(尽可能推荐):
public class MyGenericType<T extends EntityClass>
{
public <T extends EntityClass> void someMethod(final T someVar)
{
Class c = someVar.getClass();
}
}
方法二(如果需要在构建时确定,只能这样):
public class MyGenericType<T extends EntityClass>
{
private final Class<? extends EntityClass>genericClazz;
public MyGenericType(Class t)
{
genericClazz = t;
return;
}
}
由于擦除,您无法获取有关泛型类型的信息,简而言之,这意味着Java编译器不保留泛型类型信息关于生成的字节码中的实际实例。
但是,编译器不会去除实际实例的superclass的泛型类型信息。因此,您可以在具有通用类型参数的 class 的 descendant 上使用 (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>
class' 构造函数中此转换的评论:
genericClazz = (Class<? extends EntityClass>)...
由于 T
被声明为从 EntityClass
扩展而来,您不需要使用通配符。仅使用 T
就足够了:
genericClazz = (Class<T>)...
关于您得到的 ClassCastException
,那是因为在您的示例中,MyGenericType
没有通用的 superclass(实际上,它没有任何 super class,但 Object
除外,它不是 ParameterizedType
。因此,当您使用此转换时:(ParameterizedType) getClass().getGenericSuperclass()
,您将得到 ClassCastException
。
编辑:
我忘了你问的是如何做到这一点 而 不必从任何 class 扩展。一种方法是在构造函数中传递泛型类型:
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
class abstract
并让 subclasses return 成为通用类型。这可能是由泛型强制执行的,因此如果 subclass 尝试 return 错误的类型,它会得到一个编译错误:
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
}
}
我有一个像这样的简单界面。
public interface EntityClass
{
public void setId(final Integer id);
public Integer getId();
}
和一个class
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
这段代码我一直在使用它但是从 subclass 扩展但我不想我的 GenericType
从任何 class.
我该怎么做才能从此代码中获取 Student
类型。
final MyGenericType<Student>action = new MyGenericType<>();
因为我需要得到一个Hibernate namedQuery.
1) 没有不继承任何class的东西,每一样东西都是对象class的扩展,所以即使你不指定任何东西,默认情况下它将扩展对象。
2) 在泛型class中有两种获取运行时类型的方法,可以在变量上使用getClass,或者在构造函数或方法中传入class。 示例代码:
方法一(尽可能推荐):
public class MyGenericType<T extends EntityClass>
{
public <T extends EntityClass> void someMethod(final T someVar)
{
Class c = someVar.getClass();
}
}
方法二(如果需要在构建时确定,只能这样):
public class MyGenericType<T extends EntityClass>
{
private final Class<? extends EntityClass>genericClazz;
public MyGenericType(Class t)
{
genericClazz = t;
return;
}
}
由于擦除,您无法获取有关泛型类型的信息,简而言之,这意味着Java编译器不保留泛型类型信息关于生成的字节码中的实际实例。
但是,编译器不会去除实际实例的superclass的泛型类型信息。因此,您可以在具有通用类型参数的 class 的 descendant 上使用 (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>
class' 构造函数中此转换的评论:
genericClazz = (Class<? extends EntityClass>)...
由于 T
被声明为从 EntityClass
扩展而来,您不需要使用通配符。仅使用 T
就足够了:
genericClazz = (Class<T>)...
关于您得到的 ClassCastException
,那是因为在您的示例中,MyGenericType
没有通用的 superclass(实际上,它没有任何 super class,但 Object
除外,它不是 ParameterizedType
。因此,当您使用此转换时:(ParameterizedType) getClass().getGenericSuperclass()
,您将得到 ClassCastException
。
编辑:
我忘了你问的是如何做到这一点 而 不必从任何 class 扩展。一种方法是在构造函数中传递泛型类型:
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
class abstract
并让 subclasses return 成为通用类型。这可能是由泛型强制执行的,因此如果 subclass 尝试 return 错误的类型,它会得到一个编译错误:
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
}
}