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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4365095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 16:35:16  来源:igfitidea点击:

Detecting the present annotations within the given object passed into a constructor

javareflectionconstructorannotationsruntime

提问by user504342

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.

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

Details of the "problem"

“问题”详情

Lets say I have two java classes:

假设我有两个 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
}

A Line object holds Cells.

Line 对象包含单元格。

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

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 @Lineannotation for the class, and at least one @Cellannotation 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 @Cellin that object are transformed to Cell objects and added to the cells list.

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

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

Thank you for your kind help!

谢谢你的热心帮助!

采纳答案by Liviu T.

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.Classand a java.lang.reflect.Field.

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

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

注意:您需要检索私有字段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 DEFAULTand check for that value when iterating through the fields and either use the value stored in name()or the propertyName

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

回答by Jigar Joshi

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!)?

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

Yes it is very well possible using isAnnotationPresent

是的,使用isAnnotationPresent很有可能

@Deprecated
public class AnnotationDetection {

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


Notethat annotation which are scoped to retain at Runtimewill be available only,

请注意,作用域为保留的注释Runtime将仅可用,