一个关于反射,泛型的问题,欢迎讨论···

设计一个方法,传入一个class对象,返回这个class的类名,这个需求本身不难,代码如下:
[code="java"]public class GenericsTest {

protected static  <E>  String getEntityName(Class<E> clazz) {
    // TODO Auto-generated method stub
    String entityName = clazz.getSimpleName();
    Entity entity = clazz.getAnnotation(Entity.class);
    if(entity != null && !"".equals(entity.name())){
        entityName = entity.name();
    }
    return entityName;
}


public static void main(String [] args){
    GenericsTest g = new GenericsTest();
    System.out.println(GenericsTest.getEntityName(g.getClass()));
}

}[/code]

问题在于:如果我将上面的getEntityname方法的泛型参数去掉的话就会报错,编译不通过,我不明白的就是这里的到底有什么作用???我在调用getEntityname的时候并没有给他传递泛型参数,但是却不能没有这个泛型参数,这奇怪啊,欢迎讨论!!!

去掉泛型参数代码如下:
[code="java"]public class GenericsTest {

protected static   String getEntityName(Class clazz) {
    // TODO Auto-generated method stub
    String entityName = clazz.getSimpleName();
    Entity entity = clazz.getAnnotation(Entity.class);
    if(entity != null && !"".equals(entity.name())){
        entityName = entity.name();
    }
    return entityName;
}


public static void main(String [] args){
    GenericsTest g = new GenericsTest();
    System.out.println(GenericsTest.getEntityName(g.getClass()));
}

}[/code]

weixin_42639849
weixin_42639849 Class<?> clazz 类导入正确就不会报错的。
接近 8 年之前 回复

5个回答

方法改成如下即可:
[code="java"]
protected static String getEntityName(Class clazz) {
// TODO Auto-generated method stub
String entityName = clazz.getSimpleName();
Annotation anno = clazz.getAnnotation(Entity.class);
if(anno instanceof Entity)
{
Entity entity = (Entity)anno;
if(entity != null && !"".equals(entity.name())){
entityName = entity.name();
}
}
return entityName;
}
[/code]
实际上那个编译错误,跟泛型无关,而是由于class.getAnnotation返回的是Annotation,而你直接用Entity entity =class.getAnnotation导致类型转换编译时失败。

hongshengzhi
hongshengzhi 确实是这样的,非常感谢,呵呵,这么晚还在上iteye啊····
接近 8 年之前 回复
Dead_Knight
Dead_Knight 你可以通过javap -c class命令查看字节码。如果加了<E>之后,字节码中有这样一句“checkcast”检查类型转换。自动把 Entity entity = clazz.getAnnotation(Entity.class); 编译成: Entity entity = (Entity)clazz.getAnnotation(Entity.class); 所以就不会造成编译期错误了。 泛型这部分内容我也不是太深入,我觉得应该是加了<E>之后,编译器会自动对class做类型转换,不加<E>,就没有这一步操作。导致编译不通过
接近 8 年之前 回复
hongshengzhi
hongshengzhi 可是第一段代码那样却能编译通过: protected static <E> String getEntityName(Class<E> clazz) 就是在参数clazz的声明中使用泛型声明<E> 而已,这样就能通过了
接近 8 年之前 回复

Entity这个类呢?

hongshengzhi
hongshengzhi 汗,忘记说了,Entity是 JPA的一个类,在这个包下面: import javax.persistence.Entity;
接近 8 年之前 回复

就是泛型 代表的 是你传入的class可以是任意类型的、、

hongshengzhi
hongshengzhi 可是我调用方法的没有传入类啊,但是去掉又会报错
接近 8 年之前 回复

如果去掉getEntityName方法前的E, 那么GenericsTest 就是一个普通的类,自己不是泛型,getEntityName也不是泛型方法,Class clazz中的E 就无法解析,编译器不知道E是从哪来的。

要么让GenericsTest 为泛型类GenericsTest
要么就申明getEntityName为泛型方法 String getEntityName(Class clazz)

hongshengzhi
hongshengzhi 你可能看错了呢,报错的是这一句: Entity entity = clazz.getAnnotation(Entity.class); 加上泛型声明之后这一句就不报错了,为什么?这次是我想问的!
接近 8 年之前 回复

其实你要明白Class这个类就是个带有泛型定义的类。如果你把Class 变成Class 是不是会有警告。
XX.getClass()得到的是Class.所以你调用getEntityname其实是传了泛型参数进去的。

hongshengzhi
hongshengzhi 这样说似乎就可以全部解释通了呢···
接近 8 年之前 回复
hongshengzhi
hongshengzhi 谢谢啊!···
接近 8 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐