1

我看到 Class 实例具有不同的签名,至少在getAnnotation方法方面,比较 Class 对象和<some-object>.getClass()对象。

以下代码显示了一个示例案例。

@Bar("hello")
public class Foo {

    public static void main(String[] args) {

        Foo foo=new Foo();
        Bar bar1,bar2,bar3;

        Class clazz=foo.getClass();

        //This compiles and work (as expected)
        bar1=foo.getClass().getAnnotation(Bar.class);

        //This does not compile!
        bar2=clazz.getAnnotation(Bar.class);

        //This one copiles and work!
        bar3=(Bar) clazz.getAnnotation(Bar.class);

    }
}

@Retention(RetentionPolicy.RUNTIME)
@interface Bar {
    String value();
}

注意:整个示例是从我的编辑器中复制和粘贴的。

--------修改以更好地展示场景

我忘了在示例中显示“代码”不知道 Foo 的存在,例如外部库:

class SomeExternalLibrary{
    public static void someMethod(Class clazz){        
        Bar bar2,bar3;        

        bar2=clazz.getAnnotation(Bar.class);        

        //This one copiles and work!
        bar3=(Bar) clazz.getAnnotation(Bar.class);
    }
}

使用这个外部库的代码是这样的:

SomeExternalLibrary.someMethod(Foo.class);

很抱歉没有那么清楚我的场景现实:-)

4

4 回答 4

3

这个问题是关于泛型的。

编译错误的原因是你没有在clazz变量中包含类信息。

将代码更改为此将解决问题:

Class<Foo> clazz = foo.getClass();
于 2012-12-05T20:36:27.647 回答
1

另一个答案是正确的,因为它与泛型有关,但代码更改应该是:

Class<? extends Foo> clazz = foo.getClass();

在您的第二种情况下,同样的事情正在发生。由于您没有使用泛型,因此getAnnotation(Bar.class)只返回一个Annotation. 如果您要使用下面的泛型,它将起作用:

public static <T> void someMethod(Class<T> clazz) { ... }
于 2012-12-05T20:39:43.510 回答
1

getAnnotation 使用泛型定义为

<T> T getAnnotation(Class<T> clazz)

这意味着只要可以在编译时解析泛型,注释就不需要类型转换。在第二个示例中,Class clazz变量已存储为原始类型。如果您将其限定为Class<? extends Foo> clazz第二个示例将起作用。

于 2012-12-05T20:43:35.990 回答
0

我不知道为什么,但如果你使用它会起作用:

Class<?> clazz

代替

Class clazz
于 2016-10-20T12:54:31.197 回答