In che modo le diverse politiche di conservazione influiscono sulle mie annotazioni?


175

Qualcuno può spiegare in modo chiaro le differenze pratiche tra le java.lang.annotation.RetentionPolicycostanti SOURCE, CLASS, e RUNTIME?

Inoltre, non sono esattamente sicuro del significato della frase "conservazione delle annotazioni".


5

sì, ho già letto ma non capisco in pratica come funziona. In effetti, se provo "questa frase": "" "" Le annotazioni devono essere registrate nel file di classe dal compilatore, ma non è necessario che vengano mantenute dalla VM in fase di esecuzione. "" "e quindi apro una classe decompilata in cui inserisco un'annotazione con criterio di conservazione CLASS Non trovo nulla ...
xdevel2000

2
Quindi il tuo decompilatore non sembra supportare le annotazioni. jd-gui funziona bene.
musiKk,

Grazie il problema era il mio decompilatore dj e jad ... jd-gui mostramelo !!
xdevel2000,

Risposte:


210
  • RetentionPolicy.SOURCE: Scarta durante la compilazione. Queste annotazioni non hanno alcun senso dopo il completamento della compilazione, quindi non vengono scritte nel bytecode.
    Esempio: @Override,@SuppressWarnings

  • RetentionPolicy.CLASS: Scarta durante il caricamento di classe. Utile quando si esegue la post-elaborazione a livello di codice. Un po 'sorprendentemente, questo è il valore predefinito.

  • RetentionPolicy.RUNTIME: Non scartare. L'annotazione dovrebbe essere disponibile per la riflessione in fase di esecuzione. Esempio:@Deprecated

Fonte: ora il vecchio URL è morto hunter_meta e sostituito con hunter-meta-2-098036 . Nel caso anche in questo caso, sto caricando l'immagine della pagina.

Immagine (clic destro e selezionare "Apri immagine in una nuova scheda / finestra") Schermata del sito Web Oracle


1
grazie per il preventivo, il più interessante qui è il caso d'uso perRetentionPolicy.CLASS
Max

2
puoi spiegare perché RetentionPolicy.class è interessante / sorprendentemente il valore predefinito?
sudocoder

1
@sudocoder - Fare riferimento a questi collegamenti: stackoverflow.com/a/5971247/373861 e stackoverflow.com/a/3849602/373861 . Credo che questa particolare politica sia necessaria per la strumentazione bytecode. Anche se non l'ho mai usato da solo.
Favonius,

Alla fine si dice Nel prossimo articolo di questa serie, mostrerò come le capacità di riflessione di Java sono state migliorate per aiutarti a scoprire le annotazioni in fase di esecuzione e come lo strumento di elaborazione delle annotazioni "apt" ti consente di utilizzare le annotazioni in fase di compilazione. , dov'è questo articolo?
Sushant,

@Sushant: Beh, non sono sicuro di dove si trovi :). Sebbene aptsia deprecato, consultare questo docs.oracle.com/javase/7/docs/technotes/guides/apt/… . Per scoprire le annotazioni usando la riflessione ci sono più tutorial su Internet. Puoi iniziare esaminando java.lang.Class::getAnno*e metodi simili in java.lang.reflect.Methode java.lang.reflect.Field.
Favonius

57

Secondo i tuoi commenti sulla decompilazione di classe, ecco come penso che dovrebbe funzionare:

  • RetentionPolicy.SOURCE: Non verrà visualizzato nella classe decompilata

  • RetentionPolicy.CLASS: Appare nella classe decompilata, ma non può essere ispezionato in fase di esecuzione con la riflessione con getAnnotations()

  • RetentionPolicy.RUNTIME: Appare nella classe decompilata e può essere ispezionato in fase di esecuzione con la riflessione con getAnnotations()


Sì, anche io la pensavo così, ma nella classe decompilata non è presente nulla !!! e quindi sono confuso ... Proverò a ispezionare il file di classe con lo strumento
javap

javap non restituisce nulla dove vengono messi allora?
xdevel2000,

1
qualche caso d'uso di RetentionPolicy.CLASS?
Rahul,

20

Esempio eseguibile minimo

Livello linguistico :

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;
}

Livello bytecode : usando javaposserviamo che la Retention.CLASSclasse annotata ottiene un attributo di classe RuntimeInvisible :

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

mentre l' Retention.RUNTIMEannotazione ottiene un attributo di classe RuntimeVisible :

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

e l' Runtime.SOURCEannotato .classnon ottiene alcuna annotazione.

Esempi su GitHub con cui giocare.


Qualche idea su a cosa servono Runtime.SOURCE e Runtime.CLASS?
Praveen Kamath,

@PraveenKamath Non conosco alcun esempio di dove siano utili. Probabilmente succede solo se stai facendo cose JVM di livello inferiore che la maggior parte degli sviluppatori non fa mai. Fammi sapere se trovi un'applicazione per loro.
Ciro Santilli 3 冠状 病 六四 事件 法轮功

5

Criterio di conservazione: un criterio di conservazione determina in quale punto viene scartata un'annotazione. Viene specificato utilizzando le annotazioni integrate di Java: @Retention[Informazioni]

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.

0
  • CLASS : Le annotazioni devono essere registrate nel file di classe dal compilatore ma non devono essere conservate dalla VM in fase di esecuzione.
  • RUNTIME : Le annotazioni devono essere registrate nel file di classe dal compilatore e conservate dalla VM in fase di esecuzione, quindi possono essere lette in modo riflessivo.
  • SOURCE : Le compilazioni devono essere eliminate dal compilatore.

Oracle Doc

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.