2010-10-17 8 views
0

je voudrais annoter certaines classes avec une annotation @MyEntityJava: collection qui permet aux objets avec une annotation personnalisée

public @interface MyEntity {} 

@MyEntity 
public class MyClass { ... } 

Et définir une collection où seules les classes avec cette annotation sont autorisés (sans avoir besoin de les définissent comme public class MyClass implements XXX):

List<MyEntity> list = new ArrayList<MyEntity>(); 
list.add(new MyClass()) 

les résultats de code ci-dessus dans une erreur de complation "la méthode add (de MyEntity) dans le type ArrayList est pas applicable pour les arguments (MyClass)". Existe-t-il un moyen de définir une collection qui autorise uniquement les objets avec une annotation donnée?

+1

Vous voulez la sémantique * précise * d'une interface lorsque vous utilisez des annotations à la place? Pourquoi? –

Répondre

3

La réponse courte est non.

Votre problème est que List<MyEntity> définit une liste de MyEntity ou de ses sous-classes (à savoir si nous avons @interface AnotherEntity extends MyEntity alors nous pourrions mettre AnotherEntity à cette liste).

La classe MyClass ne s'étend pas/n'implémente pas MyEntity, elle est annotée avec.

Même si c'était possible, ce ne serait pas efficace. Vous ne savez pas quelles méthodes ou champs sont disponibles, MyEntity ne décrit pas l'interface de votre objet. Donc, la seule chose pour laquelle il pourrait être utilisé est de filtrer les mauvaises insertions. Vous pouvez l'implémenter facilement en fournissant votre implémentation List:

List<?> myEntities = new LinkedList<?> { 
    @Override 
    public boolean add(Object obj) { 
     if (obj != null && obj.getClass().isAnnotationPresent(MyEntity.class)) { 
      return super.add(obj); 
     } 
     throw new IllegalArgumentException("Only objects annotated with MyEntity are allowed"); 
    } 

    @Override 
    public boolean addAll(Collection<?> objs) { 
     //something similar, maybe with Collections2.filter from Google Collections 
    } 
}; 
3

Ne pensez pas que ce soit possible. Pourquoi ne pas les implémenter une interface non-méthode à la place?

1

La présence d'une annotation ne modifie pas le type de la classe annotée.

Vous pouvez créer une collection qui contient uniquement des éléments qui sont annotés avec votre annotation. Vous devez créer une classe wrapper pour la collection qui utilise la réflexion pour vérifier la présence de l'annotation lors de l'insertion. Il n'obtiendra toujours pas de vérification de type à la compilation. Pour cela vous aurez besoin de quelque chose qui affecte directement le type des éléments insérables (interface ou superclasse, etc.)

0

Il suffit de remplacer les méthodes de list: add, addAll et constructors pour filtrer les classes qui ont l'annotation attendue.

Questions connexes