Detecting the present annotations within the given object passed into a constructor
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 ce开发者_如何转开发lls list.
My questions:
- 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!)?
- is it possible to detect the datatype of the
@Cell
tagged members? This is needed because the Cell class doesn't accept all datatypes. - 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. - 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 }
- 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!
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
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,
精彩评论