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

发布于 2024-10-06 09:14:23 字数 1695 浏览 6 评论 0原文

简而言之,我的问题是:如何检测给定用户类/对象是否存在 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(name="aName"),并且仅当 @Cell<指定 /code> 时,将使用成员的名称。我不知道这些信息在运行时是否仍然可以使用反射获得。
  4. 如何检测注释是否在正确的位置?如果代码是这样标记的,那么该对象应该被忽略(或者可能抛出异常)?
    @Cell // 哦哦,这不好:(
    公共类错误类{
    // 一些成员
    }
  5. 您能否提供一些启动代码,以便我了解一些如何解决这个问题。我对注释和反射真的很陌生。顺便说一句:我正在使用最新的 jvm 1.6+

感谢您的帮助!

My question in short: how do I detect if a java annotation is present (and in the right place) for a given user class/object.

Details of the "problem"

Lets say I have two java classes:

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
}

A Line object holds Cells.

I also have two annotations, like:

public @interface Line {
  // some stuff here
}

public @interface Cell {
  // some stuff here
}

I also have a bunch of user classes (two will do for this example) that contain the @Line and @Cell annotations I specified, like:

@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;
}

The problem: When I instantiate a new Line object, I want to be able to pass the user classes/objects into the Line constructor. The Line constructor then finds out if the passed user classes/objects are valid classes that can be processed. Only user classes that have a @Line annotation for the class, and at least one @Cell annotation for its members are valid objects that can be passed into the constructor of the Line object.
All other passed objects are invalid. The moment a valid user object is passed, all the available members that are tagged as @Cell in that object are transformed to Cell objects and added to the cells list.

My questions:

  1. is this possible to detect the annotations in this object/class at runtime, and only for THIS passed object (I don't want to scan for annotations on the classpath!)?
  2. is it possible to detect the datatype of the @Cell tagged members? This is needed because the Cell class doesn't accept all datatypes.
  3. is it possible to retrieve the actual member name (specified in the java file) so that the user doesn't have to specify the members Cell name. I want the user to be able to write @Cell (without a name) and @Cell(name="aName"), and when only @Cell is specified, the name of the member is used instead. I have no idea if this information is still available at runtime using reflection.
  4. How to detect if the annotations are in the right place?If code is tagged like this, then the object should be ignored (or maybe an exception is thrown)?
    @Cell // oh oh, that's no good :(
    public class WrongClass {
    // some members
    }

  5. Could you provide some startup code, so I know a little to get going with this problem. I am really new to annotations and reflection. BTW: I am using the latest jvm 1.6+

Thank you for your kind help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

浅听莫相离 2024-10-13 09:14:23

首先,您需要对注释制定保留策略,以便可以通过反射读取它们。

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

  }

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

  }

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

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

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

First you need to have retention policy on your annotations so you can read them with reflection

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

  }

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

  }

Second you need to test if the class has the Line annotation with isAnnotationPresent(annotationClass). This method is accessible from java.lang.Class and a java.lang.reflect.Field.

NOTE: that you need to retrieve the fields that are private with class.getDeclaredField(fieldName).

3. I don't think you can make an annotation have a default value based on a propertyName but you can make name optional by providing a default String name() default DEFAULT and check for that value when iterating through the fields and either use the value stored in name() or the propertyName

沒落の蓅哖 2024-10-13 09:14:23

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));
    }
}

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

Q.1 :is this possible to detect the annotations in this object/class at runtime, and only for THIS passed object (I don't want to scan for annotations on the classpath!)?

Yes it is very well possible using isAnnotationPresent

@Deprecated
public class AnnotationDetection {

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

Note that annotation which are scoped to retain at Runtime will be available only,

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文