Как различные политики хранения влияют на мои аннотации?

175

Может кто - нибудь объяснить , в ясной форме практических различий между java.lang.annotation.RetentionPolicyконстантами SOURCE, CLASSи RUNTIME?

Я также не совсем уверен, что означает фраза «сохранение аннотации».

xdevel2000
источник
5
Документация ( java.sun.com/j2se/1.5.0/docs/api/java/lang/annotation/… ) очень понятна.
True Soft
да, я уже читал, но на практике не понимаю, как это работает. Фактически, если я попробую «эту фразу»: «» »« Аннотации должны быть записаны компилятором в файл класса, но не должны сохраняться виртуальной машиной во время выполнения. "" ", а затем откройте декомпилированный класс, в который я поместил аннотацию с политикой хранения CLASS. Я ничего не нахожу ...
xdevel2000
2
Тогда ваш декомпилятор не поддерживает аннотации. JD-GUI работает нормально.
MusiKk
Спасибо, проблема была в том, что мои декомпиляторы dj и jad ... jd-gui показали мне !!
xdevel2000

Ответы:

210
  • RetentionPolicy.SOURCE: Сбросить во время компиляции. Эти аннотации не имеют никакого смысла после завершения компиляции, поэтому они не записываются в байт-код.
    Пример: @Override,@SuppressWarnings

  • RetentionPolicy.CLASS: Сбросить во время загрузки класса. Полезно при выполнении постобработки на уровне байт-кода. Несколько удивительно, это по умолчанию.

  • RetentionPolicy.RUNTIME: Не выбрасывайте. Аннотация должна быть доступна для размышления во время выполнения. Пример:@Deprecated

Источник: старый URL мертв, теперь hunter_meta и заменен на hunter-meta-2-098036 . В случае, если даже это не работает, я загружаю изображение страницы.

Изображение (щелкните правой кнопкой мыши и выберите «Открыть изображение в новой вкладке / окне») Снимок экрана сайта Oracle

Favonius
источник
1
спасибо за цитату, самый интересный здесь случай использованияRetentionPolicy.CLASS
Макс
2
Можете ли вы объяснить, почему RetentionPolicy.class интересен / удивительно по умолчанию?
Судокодер
1
@sudocoder - см. следующие ссылки: stackoverflow.com/a/5971247/373861 и stackoverflow.com/a/3849602/373861 . Я считаю, что эта конкретная политика необходима для инструментария байт-кода. Хотя сам никогда этим не пользовался.
Фавониус
В конце говорится: В следующей статье этой серии я покажу, как были расширены возможности отражения в Java, чтобы помочь вам находить аннотации во время выполнения, и как инструмент обработки аннотаций «apt» позволяет вам использовать аннотации во время сборки. где эта статья?
Sushant
@Sushant: Ну, я не уверен, где это :). Хотя aptэто устарело, обратитесь к этому docs.oracle.com/javase/7/docs/technotes/guides/apt/… . Для обнаружения аннотации с помощью рефлексии в Интернете есть несколько учебных пособий. Вы можете начать с изучения java.lang.Class::getAnno*и аналогичных методов в java.lang.reflect.Methodи java.lang.reflect.Field.
Фавониус
57

Согласно вашим комментариям о декомпиляции классов, вот как я думаю, что это должно работать:

  • RetentionPolicy.SOURCE: Не появится в декомпилированном классе

  • RetentionPolicy.CLASS: Появляются в декомпилированном классе, но не могут быть проверены во время выполнения с отражением getAnnotations()

  • RetentionPolicy.RUNTIME: Появляются в декомпилированном классе и могут быть проверены во время выполнения с помощью getAnnotations()

ewernli
источник
Да тоже мне так показалось но в декомпилированном классе ничего нету !!! и поэтому я в замешательстве ... Я попытаюсь проверить файл класса с помощью инструмента
javap
javap ничего не возвращает куда ставится тогда?
xdevel2000
1
любой случай использования RetentionPolicy.CLASS?
Рахул
20

Минимальный исполняемый пример

Уровень языка :

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

Уровень байт-кода : при использовании javapмы видим, что Retention.CLASSаннотированный класс получает атрибут класса RuntimeInvisible :

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

в то время как Retention.RUNTIMEаннотация получает атрибут класса RuntimeVisible :

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

и Runtime.SOURCEаннотированный .classне получает никаких аннотаций.

Примеры на GitHub для вас, чтобы играть с.

Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник
Итак, есть идеи, что такое использование Runtime.SOURCE и Runtime.CLASS?
Правин Камат
@PraveenKamath Я не знаю ни одного примера, где они полезны. Скорее всего, это происходит, только если вы делаете JVM более низкого уровня, чего никогда не делает большинство разработчиков. Дайте мне знать, если вы найдете приложение для них.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
5

Политика хранения. Политика хранения определяет, в какой момент аннотация отклоняется. Это указывается с помощью встроенных аннотаций Java: @Retention[About]

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
  • КЛАСС : аннотации должны быть записаны в файле классов компилятором, но не должны сохраняться виртуальной машиной во время выполнения.
  • RUNTIME : аннотации должны быть записаны компилятором в файл класса и сохранены виртуальной машиной во время выполнения, чтобы их можно было читать рефлексивно.
  • ИСТОЧНИК : аннотации должны быть отброшены компилятором.

Oracle Doc

Майкл Вонг
источник