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

简而言之,我的问题是:我如何检测给定用户类/对象是否存在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 对象保存单元格。

我还有两个注释,例如:

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+

感谢您的帮助!


答案 1

首先,您需要在批注上设置保留策略,以便可以通过反射来读取它们

  @Retention(RetentionPolicy.RUNTIME)
  @Target(ElementType.TYPE)
  public static @interface Line {

  }

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

  }

其次,您需要测试该类是否具有带有 的 Line 注释。此方法可从 java.lang.reflect.Field 访问。isAnnotationPresent(annotationClass)java.lang.Class

注意:您需要检索带有 的私有字段。class.getDeclaredField(fieldName)

3.我不认为您可以根据属性名称使注释具有默认值,但是您可以通过提供默认值并使名称可选,并在循环访问字段时检查该值,并使用存储在中的值或String name() default DEFAULTname()propertyName


答案 2

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

是的,使用isAnnotationPresent是很有可能的

@Deprecated
public class AnnotationDetection {

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

请注意,在运行时保留范围的注释将仅可用,