Jak różne zasady przechowywania wpływają na moje adnotacje?

175

Czy ktoś może wyjaśnić w jasny sposób praktycznych różnic między java.lang.annotation.RetentionPolicystałymi SOURCE, CLASSi RUNTIME?

Nie jestem też do końca pewien, co oznacza wyrażenie „zachowanie adnotacji”.

xdevel2000
źródło
5
Dokumentacja ( java.sun.com/j2se/1.5.0/docs/api/java/lang/annotation/… ) jest bardzo przejrzysta.
True Soft
tak, już czytałem, ale w praktyce nie rozumiem, jak to działa. W rzeczywistości, jeśli spróbuję 'ta fraza': "" "" Adnotacje mają być zapisane w pliku klasy przez kompilator, ale nie muszą być zachowywane przez maszynę wirtualną w czasie wykonywania. „” ”, a następnie otwórz zdekompilowaną klasę, w której umieszczam adnotację z polityką przechowywania KLASA Nic nie znajduję ...
xdevel2000
2
Wygląda na to, że Twój dekompilator nie obsługuje adnotacji. jd-gui działa dobrze.
musiKk
Dzięki, problemem był mój dekompilator dj i jad ... jd-gui pokaż mi !!
xdevel2000

Odpowiedzi:

210
  • RetentionPolicy.SOURCE: Odrzuć podczas kompilacji. Te adnotacje nie mają żadnego sensu po zakończeniu kompilacji, więc nie są zapisywane w kodzie bajtowym.
    Przykład: @Override,@SuppressWarnings

  • RetentionPolicy.CLASS: Odrzuć podczas wczytywania klasy. Przydatne podczas przetwarzania końcowego na poziomie kodu bajtowego. Nieco zaskakujące jest to ustawienie domyślne.

  • RetentionPolicy.RUNTIME: Nie wyrzucaj. Adnotacja powinna być dostępna do refleksji w czasie wykonywania. Przykład:@Deprecated

Źródło: stary adres URL jest teraz martwy hunter_meta i zastąpiony przez hunter-meta-2-098036 . Na wypadek, gdyby to się zdarzyło, przesyłam obraz strony.

Obraz (kliknij prawym przyciskiem myszy i wybierz „Otwórz obraz w nowej karcie / oknie”) Zrzut ekranu witryny internetowej Oracle

Favonius
źródło
1
dzięki za cytat, najciekawszy tutaj jest przypadek użyciaRetentionPolicy.CLASS
Max
2
czy możesz wyjaśnić, dlaczego RetentionPolicy.class jest interesujący / zaskakująco domyślny?
sudocoder
1
@sudocoder - skorzystaj z tych linków: stackoverflow.com/a/5971247/373861 i stackoverflow.com/a/3849602/373861 . Wierzę, że ta konkretna polityka jest potrzebna do instrumentacji kodu bajtowego. Chociaż sam go nigdy nie używał.
Favonius
Na końcu jest napisane W następnym artykule z tej serii pokażę, w jaki sposób ulepszono możliwości odzwierciedlania języka Java, aby pomóc Ci w odkrywaniu adnotacji w czasie wykonywania, oraz w jaki sposób narzędzie do przetwarzania adnotacji „apt” umożliwia korzystanie z adnotacji w czasie kompilacji. , gdzie jest ten artykuł?
Sushant,
@Sushant: Cóż, nie jestem pewien, gdzie to jest :). Chociaż aptjest przestarzały, zapoznaj się z tym docs.oracle.com/javase/7/docs/technotes/guides/apt/… . W Internecie dostępnych jest wiele samouczków do odkrywania adnotacji za pomocą refleksji. Możesz zacząć od przyjrzenia się java.lang.Class::getAnno*i podobnym metodom w java.lang.reflect.Methodi java.lang.reflect.Field.
Favonius
57

Zgodnie z twoimi komentarzami na temat dekompilacji klas, oto jak myślę, że powinno to działać:

  • RetentionPolicy.SOURCE: Nie pojawi się w zdekompilowanej klasie

  • RetentionPolicy.CLASS: Pojawiają się w zdekompilowanej klasie, ale nie można ich sprawdzić w czasie wykonywania za pomocą odbicia z getAnnotations()

  • RetentionPolicy.RUNTIME: Pojawiają się w zdekompilowanej klasie i można je sprawdzić w czasie wykonywania za pomocą refleksji za pomocą getAnnotations()

ewernli
źródło
Tak, ja też tak myślałem, ale w zdekompilowanej klasie nie ma nic !!! i dlatego jestem zdezorientowany ... spróbuję sprawdzić plik klasy za pomocą narzędzia
javap
javap nie zwraca niczego, gdzie wtedy są umieszczone?
xdevel2000
1
jakikolwiek przypadek użycia RetentionPolicy.CLASS?
Rahul,
20

Minimalny przykład do uruchomienia

Poziom języka :

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

Poziom kodu bajtowego : używając javapobserwujemy, że Retention.CLASSklasa z adnotacjami otrzymuje atrybut klasy RuntimeInvisible :

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

podczas gdy Retention.RUNTIMEadnotacja pobiera atrybut klasy RuntimeVisible :

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

a Runtime.SOURCEadnotacja .classnie otrzymuje adnotacji.

Przykłady na GitHub, z którymi możesz się bawić.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
źródło
Więc masz jakiś pomysł, jaki jest pożytek z Runtime.SOURCE i Runtime.CLASS?
Praveen Kamath
@PraveenKamath Nie znam żadnego przykładu, gdzie są przydatne. Prawdopodobnie dzieje się tak tylko wtedy, gdy robisz rzeczy JVM niższego poziomu, których większość programistów nigdy nie robi. Daj mi znać, jeśli znajdziesz dla nich aplikację.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
5

Zasady przechowywania: zasady przechowywania określają, w którym momencie adnotacja jest odrzucana. Jest to określone za pomocą wbudowanych adnotacji Java: @Retention[Informacje]

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
źródło
0
  • KLASA : Adnotacje mają być zapisane w pliku klasy przez kompilator, ale nie muszą być zachowywane przez maszynę wirtualną w czasie wykonywania.
  • RUNTIME : Adnotacje mają być zapisane w pliku klasy przez kompilator i zachowane przez maszynę wirtualną w czasie wykonywania, aby można je było odczytać w sposób refleksyjny.
  • ŹRÓDŁO : Adnotacje mają zostać odrzucone przez kompilator.

Oracle Doc

Michael Wong
źródło