Ma question en bref: comment détecter si une annotation Java est présente (et au bon endroit) pour une classe/un objet utilisateur donné).
Détails du "problème"
Disons que j'ai deux 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
}
Un objet Line contient des cellules.
J'ai également deux annotations, comme:
public @interface Line {
// some stuff here
}
public @interface Cell {
// some stuff here
}
J'ai également un tas de classes d'utilisateurs (deux feront pour cet exemple) qui contiennent les annotations @Line et @Cell que j'ai spécifiées, comme:
@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;
}
Le problème: lorsque j'instancie un nouvel objet Line, je veux pouvoir passer les classes/objets utilisateur dans le constructeur Line. Le constructeur Line recherche ensuite si les classes/objets utilisateur transmis sont des classes valides qui peuvent être traitées. Seules les classes d'utilisateurs qui ont une annotation @Line
Pour la classe et au moins une annotation @Cell
Pour ses membres sont des objets valides qui peuvent être passés dans le constructeur de l'objet Line. Tous les autres objets transmis ne sont pas valides. Au moment où un objet utilisateur valide est passé, tous les membres disponibles marqués comme @Cell
Dans cet objet sont transformés en objets Cell et ajoutés à la liste des cellules.
Mes questions:
@Cell
? Cela est nécessaire car la classe Cell n'accepte pas tous les types de données.@Cell
(Sans nom) et @Cell(name="aName")
, et lorsque seul @Cell
Est spécifié, le nom du membre est utilisé à la place. Je ne sais pas si ces informations sont toujours disponibles à l'exécution en utilisant la réflexion.@Cell // oh oh, that's no good :(
public class WrongClass {
// some members
}
Merci pour ton aide!
Vous devez d'abord avoir une politique de rétention sur vos annotations afin de pouvoir les lire avec réflexion
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public static @interface Line {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public static @interface Cell {
}
Ensuite, vous devez tester si la classe a l'annotation Line avec isAnnotationPresent(annotationClass)
. Cette méthode est accessible à partir de Java.lang.Class
Et d'un Java.lang.reflect.Field.
NOTE : que vous devez récupérer les champs qui sont privés avec class.getDeclaredField(fieldName)
.
3.
Je ne pense pas que vous puissiez faire une annotation avoir une valeur par défaut basée sur un nom de propriété mais vous pouvez rendre le nom facultatif en fournissant une String name() default DEFAULT
par défaut et vérifier cette valeur lors de l'itération à travers le et utilisez la valeur stockée dans name()
ou propertyName
Q.1: est-il possible de détecter les annotations dans cet objet/classe lors de l'exécution, et uniquement pour CET objet passé (je ne veux pas rechercher des annotations sur le chemin de classe!)?
Oui, c'est très bien possible en utilisant isAnnotationPresent
@Deprecated
public class AnnotationDetection {
public static void main(String[] args) {
AnnotationDetection annotationDetection = new AnnotationDetection();
System.out.println(annotationDetection.getClass().isAnnotationPresent(Deprecated.class));
}
}
Notez que les annotations dont la portée est conservée à Runtime
seront disponibles uniquement,