views:

47

answers:

4

I'd like to annotate some classes with a @MyEntity annotation

public @interface MyEntity {}

@MyEntity
public class MyClass { ... }

And define a collection where only classes with that annotation are allowed (with no need to define them as public class MyClass implements XXX):

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

The above code results in a complation error "The method add(MyEntity) in the type ArrayList is not applicable for the arguments (MyClass)". Is there a way to define a collection that only allows objects with a given annotation?

+2  A: 

Don't think this is possible. Why not have them implement a no-method interface instead?

SimonJ
+3  A: 

The short answer is no.

Your problem is that List<MyEntity> defines a list of MyEntity's or its subclasses (i.e. if we have @interface AnotherEntity extends MyEntity then we could put AnotherEntity to this list).

Class MyClass doesn't extend/implement MyEntity, it's annotated with it.

Even if it was possible, it wouldn't be efficient. You wouldn't know which methods or fields are available, MyEntity doesn't describe your object's interface. So, the only thing it could be used for is filtering wrong insertions. You can implement it easily providing your List implementation:

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
   }
};
Roman
+1  A: 

The presence of an annotation doesn't modify the annotated class's type.

You could create a collection that only contains elements which are annotated with your annotation. You would need to make a wrapper class for the collection that uses reflection to check for the presence of the annotation on insertion.

It still won't get you compile-time type checking. For that you would need something which directly affects the insertable items' type (interface or superclass, etc.)

codelark
A: 

Just override methods of list: add, addAll and constructors, to filter classes that have expected annotation.

Dewfy