检测传递给构造函数的给定对象中的当前注释

时间:2010-12-06 09:51:11

标签: java reflection constructor annotations runtime

简而言之:我如何检测给定用户类/对象是否存在(并且在正确的位置)java注释。

“问题”的详情

假设我有两个java类:

public class Line {
   private List<Cell> cells;

   public Line(Object... annotatedObjects) {
     // check if annotations @Line and @Cell are present in annotatedObjects.
   }

   // getter/setter for cells.
}

public class Cell {
   // some members
   // some methods
}

Line对象包含Cells。

我还有两个注释,例如:

public @interface Line {
  // some stuff here
}

public @interface Cell {
  // some stuff here
}

我还有一堆用户类(本例中有两个用户类)包含我指定的@Line和@Cell注释,如:

@Line(name="pqr", schema="three")
public class AUserClass {
   @Cell
   private String aString;
}

@Line(name="xyz", schema="four")
public class AnotherUserClass {
   @Cell(name="birthday")
   private Date aDate;
}

问题:当我实例化一个新的Line对象时,我希望能够将用户类/对象传递给Line构造函数。然后,Line构造函数会查明传递的用户类/对象是否是可以处理的有效类。只有对该类具有@Line注释的用户类,以及其成员的至少一个@Cell注释才是可以传递到Line对象的构造函数的有效对象。 所有其他传递的对象都无效。传递有效用户对象的那一刻,该对象中标记为@Cell的所有可用成员都将转换为Cell对象并添加到单元格列表中。

我的问题:

  1. 这可以在运行时检测此对象/类中的注释,并且只能用于此传递的对象(我不想在类路径上扫描注释!)?
  2. 是否可以检测@Cell标记成员的数据类型?这是必需的,因为Cell类不接受所有数据类型。
  3. 是否可以检索实际的成员名称(在java文件中指定),以便用户不必指定成员Cell名称。我希望用户能够编写@Cell(没有名称)和@Cell(name="aName"),并且当仅指定@Cell时,将使用成员的名称。我不知道这些信息在运行时是否仍然可以使用反射。
  4. 如何检测注释是否在正确的位置?如果代码被标记为这样,那么应该忽略该对象(或者可能抛出异常)?
    @Cell // oh oh, that's no good :(
    public class WrongClass {
    // some members
    }
  5. 你能提供一些启动代码吗,所以我知道一点这个问题。我对注释和反思都很陌生。顺便说一句:我使用的是最新的jvm 1.6 +
  6. 感谢您的帮助!

2 个答案:

答案 0 :(得分:43)

首先,您需要在注释上设置保留政策,以便您可以使用反射

来阅读它们
  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public static @interface Line {

  }

  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.FIELD)
  public static @interface Cell {

  }

其次,您需要测试该类是否具有isAnnotationPresent(annotationClass)的行注释。可以从java.lang.Class和java.lang.reflect.Field。

访问此方法

注意:您需要检索class.getDeclaredField(fieldName)专用的字段。

3.我认为您不能使注释具有基于propertyName的默认值,但您可以通过提供默认值String name() default DEFAULT使名称成为可选,并在迭代时检查该值字段,并使用name()propertyName

中存储的值

答案 1 :(得分:20)

  

问题1:这是否可以在运行时检测此对象/类中的注释,并且仅针对此传递的对象(我不想扫描类路径上的注释!)?

是的,使用isAnnotationPresent

非常有效
@Deprecated
public class AnnotationDetection {

    public static void main(String[] args) {
        AnnotationDetection annotationDetection = new AnnotationDetection();
        System.out.println(annotationDetection.getClass().isAnnotationPresent(Deprecated.class));
    }
}

注意仅限于Runtime保留作用域的注释,