假设如下:
@SomeAnnotation public interface Foo { }
我想知道,SomeAnnotation的定义类加载器是否等于或者是Foo的启动类加载器的父级是否总是这样.
我已经读了JVMS v8 section 5.3.但我不知道这里适用.第5.3.4节讨论了加载约束,但是它们似乎不适用于注释.
我问的问题是因为这样的代码:
Class<?> fooClass = //will in some way obtain a reference to class Foo fooClass.getAnnotation(SomeAnnotation.class);
在不同的类加载器的存在下将失败.我知道我可以使用getAnnotations并在结果数组中搜索类名称等于SomeAnnotation的元素.但是我想知道以下是否也可以:
Class<?> fooClass = //will in some way obtain a reference to class Foo fooClass.getAnnotation((Class<? extends Annotation>) fooClass .getClassLoader().loadClass(SomeAnnotation.class.getName()));
解决方法
简短的答案:不
长的答案.
RetentionPolicy.RUNTIME注释只能通过反射API进行发现.这样做是为了确保注释和注释代码之间的松耦合.根据this bug report,getAnnotations()必须跳过未知的注释,这意味着注释不能被类加载器识别.讨论的真实Java代码的行为here证实了这一假设.
这种行为有两个含义:
>所有无法识别的注释(例如不在类路径中的注释)变为“不可见”
>为了揭示它们,类必须被一个可以访问这两个类型和注释的不同类加载器完全重新加载.
例如,如果somepkg.SomeAnnotation在加载someClass时不在类路径中,这将不起作用:
Class<?> someClass = .... URL [] classPathWithAnnotations = .... ClassLoader cl = new URLClassLoader(classPathWithAnnotations); Annotation a = someClass.getAnnotation(cl.loadClass("somepkg.SomeAnnotation")); // a will be null
但这将:
Class<?> someClass = .... URL [] classPathWithSomeClassAndAnnotations = .... ClassLoader cl = new URLClassLoader(classPathWithSomeClassAndAnnotations,null); Annotation a = cl.loadClass(someClass.getName()).getAnnotation(cl.loadClass("somepkg.SomeAnnotation"));