2015-03-13 52 views
2

我有一个这样的简单的界面。Java获取通用类型不扩展

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

只有这样,才能捕捉在泛型类型信息运行时通过'extends'语句。任何其他类型的信息都将被删除。 – Jonathan 2015-03-13 19:33:51

回答

1

你由于删除,简而言之,这意味着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:

另一种方法是使你的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 
    } 
} 
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; 
    }   
}