¿Cómo afectan las diferentes políticas de retención a mis anotaciones?

175

¿Alguien puede explicar de una manera clara las diferencias prácticas entre las java.lang.annotation.RetentionPolicyconstantes SOURCE, CLASSy RUNTIME?

Tampoco estoy exactamente seguro de lo que significa la frase "retener la anotación".

xdevel2000
fuente
55
La documentación ( java.sun.com/j2se/1.5.0/docs/api/java/lang/annotation/… ) es muy clara.
True Soft
Sí, ya leí pero en la práctica no entiendo cómo funciona. De hecho, si intento 'esta frase': "" "" El compilador debe registrar las anotaciones en el archivo de clase, pero la VM no debe retenerlas en tiempo de ejecución. "" "y luego abro una clase descompilada donde pongo una anotación con la política de retención CLASE No encuentro nada ...
xdevel2000
2
Entonces su descompilador no parece admitir anotaciones. jd-gui funciona bien.
musiKk
Gracias el problema fue mi descompilador dj y jad ... jd-gui muéstrame !!
xdevel2000

Respuestas:

210
  • RetentionPolicy.SOURCE: Descartar durante la compilación. Estas anotaciones no tienen ningún sentido después de que se haya completado la compilación, por lo que no están escritas en el código de bytes.
    Ejemplo: @Override,@SuppressWarnings

  • RetentionPolicy.CLASS: Descartar durante la carga de clase. Útil cuando se realiza un procesamiento posterior a nivel de código de bytes. Sorprendentemente, este es el valor predeterminado.

  • RetentionPolicy.RUNTIME: No descartes. La anotación debe estar disponible para la reflexión en tiempo de ejecución. Ejemplo:@Deprecated

Fuente: la antigua URL está muerta ahora hunter_meta y reemplazada por hunter-meta-2-098036 . En caso de que incluso esto se caiga, estoy cargando la imagen de la página.

Imagen (haga clic con el botón derecho y seleccione 'Abrir imagen en nueva pestaña / ventana') Captura de pantalla del sitio web de Oracle

Favonio
fuente
1
gracias por la cita, la más interesante aquí es el caso de uso paraRetentionPolicy.CLASS
Max
2
¿Puedes explicar por qué RetentionPolicy.class es interesante / sorprendentemente el predeterminado?
sudocoder
1
@sudocoder: consulte estos enlaces: stackoverflow.com/a/5971247/373861 y stackoverflow.com/a/3849602/373861 . Creo que esta política particular es necesaria para la instrumentación de bytecode. Aunque nunca lo usé yo mismo.
Favonio el
Al final dice: En el siguiente artículo de esta serie, mostraré cómo se han mejorado las capacidades de reflexión de Java para ayudarlo a descubrir anotaciones en tiempo de ejecución y cómo la herramienta de procesamiento de anotaciones "apt" le permite usar anotaciones en tiempo de compilación. ¿Dónde está este artículo?
Sushant
@Sushant: Bueno, no estoy seguro de dónde está :). Aunque aptestá en desuso, consulte docs.oracle.com/javase/7/docs/technotes/guides/apt/… . Para descubrir anotaciones usando la reflexión, hay múltiples tutoriales en internet. Puede comenzar buscando java.lang.Class::getAnno*y métodos similares en java.lang.reflect.Methody java.lang.reflect.Field.
Favonio
57

Según sus comentarios sobre la descompilación de clases, así es como creo que debería funcionar:

  • RetentionPolicy.SOURCE: No aparecerá en la clase descompilada

  • RetentionPolicy.CLASS: Aparece en la clase descompilada, pero no se puede inspeccionar en tiempo de ejecución con reflexión con getAnnotations()

  • RetentionPolicy.RUNTIME: Aparece en la clase descompilada y se puede inspeccionar en tiempo de ejecución con reflexión con getAnnotations()

ewernli
fuente
Sí, yo también lo pensé, pero en la clase descompilada no hay nada presente. y por lo tanto estoy confundido ... Trataré de inspeccionar el archivo de clase con la herramienta javap
xdevel2000
javap no devuelve nada donde se ponen entonces?
xdevel2000
1
Cualquier caso de uso de RetentionPolicy.CLASS?
Rahul
20

Ejemplo ejecutable mínimo

Nivel de idioma :

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.SOURCE)
@interface RetentionSource {}

@Retention(RetentionPolicy.CLASS)
@interface RetentionClass {}

@Retention(RetentionPolicy.RUNTIME)
@interface RetentionRuntime {}

public static void main(String[] args) {
    @RetentionSource
    class B {}
    assert B.class.getAnnotations().length == 0;

    @RetentionClass
    class C {}
    assert C.class.getAnnotations().length == 0;

    @RetentionRuntime
    class D {}
    assert D.class.getAnnotations().length == 1;
}

Nivel de código de bytes : mediante el uso javapobservamos que la Retention.CLASSclase anotada obtiene un atributo de clase RuntimeInvisible :

#14 = Utf8               LRetentionClass;
[...]
RuntimeInvisibleAnnotations:
  0: #14()

mientras que la Retention.RUNTIMEanotación obtiene un atributo de clase RuntimeVisible :

#14 = Utf8               LRetentionRuntime;
[...]
RuntimeVisibleAnnotations:
  0: #14()

y el Runtime.SOURCEanotado .classno recibe ninguna anotación.

Ejemplos en GitHub para que juegues.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fuente
¿Alguna idea de cuál es el uso de Runtime.SOURCE y Runtime.CLASS?
Praveen Kamath
@PraveenKamath No conozco ningún ejemplo donde sean útiles. Probablemente solo sucede si estás haciendo cosas JVM de nivel inferior que la mayoría de los desarrolladores nunca hacen. Avíseme si encuentra una aplicación para ellos.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
5

Política de retención: una política de retención determina en qué momento se descarta una anotación. Se especifica utilizando las anotaciones incorporadas de Java: @Retention[Acerca de]

1.SOURCE: annotation retained only in the source file and is discarded
          during compilation.
2.CLASS: annotation stored in the .class file during compilation,
         not available in the run time.
3.RUNTIME: annotation stored in the .class file and available in the run time.
Ferdous Wahid
fuente
0
  • CLASE : El compilador debe registrar las anotaciones en el archivo de clase, pero la VM no debe retenerlas en tiempo de ejecución.
  • TIEMPO DE EJECUCIÓN : el compilador registrará las anotaciones en el archivo de clase y la VM las retendrá en el tiempo de ejecución, para que puedan leerse reflexivamente.
  • FUENTE : Las anotaciones deben ser descartadas por el compilador.

Oracle Doc

Michael Wong
fuente