2010-09-10 18 views
16

Esto me desconcierta. Tengo una clase con una anotación personalizada y no puedo verificar que la anotación esté presente. ¿Qué estoy haciendo mal aquí? Si me quedo MyOperationTest (ver más abajo), me sale esto como resultado:anotación invisible?

implements Library.Operation: true 
has @Library.Marker: false 
Tada! 

Library.java:

package com.example.gotchas; 

public class Library { 
    private Library() {} 

    public @interface Marker {} 

    public interface Operation { 
     public void execute(); 
    } 
} 

MyOperation.java:

package com.example.gotchas; 

@Library.Marker 
public class MyOperation implements Library.Operation { 
    @Override public void execute() { 
     System.out.println("Tada!"); 
    } 
} 

MyOperationTest. java:

package com.example.gotchas; 

public class MyOperationTest { 
    static public void main(String[] args) 
    { 
     try { 
      Class<?> cl = Class.forName("com.example.gotchas.MyOperation"); 
      boolean implementsLibraryOperation = 
       Library.Operation.class.isAssignableFrom(cl); 
      boolean hasLibraryMarker = 
       cl.isAnnotationPresent(Library.Marker.class); 
      System.out.println("implements Library.Operation: " 
        +implementsLibraryOperation); 
      System.out.println("has @Library.Marker: "+hasLibraryMarker); 
      if (implementsLibraryOperation) 
      { 
       Class<? extends Library.Operation> opClass = 
        cl.asSubclass(Library.Operation.class); 
       Library.Operation op = opClass.newInstance(); 
       op.execute(); 
      } 
     } 
     catch (ClassNotFoundException e) { 
      e.printStackTrace(); 
     } 
     catch (InstantiationException e) { 
      e.printStackTrace(); 
     } 
     catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Respuesta

26

tiene que definir @Retention para su anotación:

@Retention(RetentionPolicy.RUNTIME) 
public @interface Marker {} 

De lo contrario la anotación no se conserva en tiempo de ejecución.

(También puede agregar explícita @Target(ElementType.TYPE) si desea limitar el uso de su anotación sólo en clases)

Como comentario - no es una práctica común para definir las anotaciones como las clases internas.

+0

De acuerdo. De manera predeterminada, la anotación no se conserva a través del tiempo de ejecución ... después de que se haya eliminado el tiempo de compilación. Por lo tanto, cuando ejecuta su código de prueba, la anotación ya no forma parte del código compilado. – RonU

+4

Más detalles en [RetentionPolicy javadoc] (http://download.oracle.com/javase/6/docs/api/java/lang/annotation/RetentionPolicy.html): * RUNTIME - Las anotaciones deben registrarse en el archivo de clase por el compilador y retenido por la máquina virtual en tiempo de ejecución, ** para que puedan leerse reflexivamente **. * – BalusC

+0

¡ah! ¡¡¡¡¡Gracias!!!!! –

2

De forma predeterminada, la política de retención de anotaciones es CLASS, lo que no hace que su anotación esté disponible para la reflexión. Debe calificarlo al declarar la anotación.