2014-01-16 21 views
1

为了理解Java注释,我尝试了一些操作并获得了一些疑惑,即使看着执行,我仍然感到困惑。这是我正在做的。 定义注解反射库是否忽略RetentionPolicy

@Retention(RetentionPolicy.CLASS) 
@Target(value=ElementType.TYPE) 
public @interface Command { 

} 

现在我初始化命令

 Reflections reflections = new Reflections(CMDS_PACKAGE); 
     Set<Class<?>> allClasses = reflections.getTypesAnnotatedWith(Command.class); // line 2 

     for (Class clazz : allClasses) { 
      MYCommand cmd = (MYCommand) clazz.newInstance(); 
      System.out.println(cmd.getClass().getAnnotation(Command.class));// line 6 
      log.info("loading Command [ {} ]", clazz.getCanonicalName()); 
     } 

当我运行的程序行6个显示null。 当策略为RetentionPolicy.RUNTIME时,第6行显示正确的命令。

在这个过程中,第2行仍然给我正确的带注释的类,而不考虑策略。那么这是否意味着Reflection Library忽略了RetentionPolicy

即使阅读了大部分教程,我仍然很困惑。

对我来说问题其实就是这个,为什么这种不同的行为?当用RetentionPolicy.CLASS策略注释它在运行时不应该给我。我的理解是错误的,还是任何人都可以分享那些对这两者理解的宝贵意见。

+0

好吧,似乎它忽略了它。但是问题是什么? – Holger

+0

@霍尔:谢谢你,我编辑了这个问题了解更多细节。 – chaosguru

回答

0

是的,Reflections library(不反射,但反射* s *)默认情况下会忽略注释的可见性。 这可以使用org.reflections.adapters.JavassistAdapter#includeInvisibleTag标志进行更改。例如:

JavassistAdapter mdAdapter = new JavassistAdapter(); 
mdAdapter.includeInvisibleTag = false; 

new Reflections(new ConfigurationBuilder() 
    ... 
    .setMetadataAdapter(mdAdapter) 
    ... 

另一种选择是使用JavaReflectionAdapter代替。

HTH

+1

哦好吧,但不应该坚持注解保留。政策。? – chaosguru

0

首先,RetentionPolicy指示符合的编译器必须做什么。 Annotation s与RetentionPolicy.SOURCE不会将它放到类文件中,而其他两个RetentionPolicy.CLASSRetentionPolicy.RUNTIME存储在类文件中,但使用不同的属性允许在读取类文件时区分它们。

documentation of RetentionPolicy.CLASS说:

注解是记录在编译器的类文件,但不必由虚拟机在运行时被保留。这是默认行为。

这里,责任明确记载,在VM不得保留他们和内置于JRE反射API遵循它。虽然“不需要保留”似乎不是一个强有力的要求。

但您正在使用的第三方库如Reflection Library可以在解析类文件时自由实现他们想要的任何内容。由于您调用的方法的文档只是说:“使用给定注释获取注释类型”,因为该类型具有该注释,所以行为并不错。

而你甚至能够通过分析AnnotationAnnotations调用该方法之前找出AnnotationRetentionPolicy。所以当你已经知道该注释具有RetentionPolicy.CLASS时,调用该方法是没有意义的,然后再打扰,因为该方法做了什么而不是什么。

但是,当然,如果这种行为完全记录下来会更好。因此,您可能会要求该第三方库的作者改进文档。

+0

谢谢你的解释 – chaosguru