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

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

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

Ответ 1

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

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

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

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

Изображение (щелкните правой кнопкой мыши и выберите "Открыть изображение в новой вкладке/окне" ) enter image description here

Ответ 2

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

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

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

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

Ответ 3

Минимальный пример runnable

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

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 для вас.

Ответ 4

Политика хранения: политика хранения определяет, в какой момент аннотация будет отброшена.

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.

Политика хранения указывается с использованием встроенных аннотаций Java: @Retention.