Як різні політики зберігання впливають на мої примітки?


175

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

Я також не зовсім впевнений, що означає фраза "збереження анотації".



так, я вже читав, але на практиці не розумію, як це працює. Насправді, якщо я спробую 'цю фразу': "" "" Анотації слід записати у файл класу компілятором, але їх не потрібно зберігати за допомогою VM під час виконання. "" ", а потім відкрити декомпільований клас, куди я
поміщаю

2
Тоді, здається, ваш декомпілятор не підтримує приміток. jd-gui прекрасно працює.
musiKk

Завдяки проблемі був мій декомпілятор dj та jad ... jd-gui покажи мені !!
xdevel2000

Відповіді:


210
  • RetentionPolicy.SOURCE: Відкинути під час компіляції. Ці анотації не мають сенсу після завершення компіляції, тому вони не записуються в байт-код.
    Приклад: @Override,@SuppressWarnings

  • RetentionPolicy.CLASS: Відмовитися під час завантаження класу. Корисно при виконанні післяобробки на рівні байт-коду. Дещо дивно, що це за замовчуванням.

  • RetentionPolicy.RUNTIME: Не відкидайте. Анотація повинна бути доступною для роздумів під час виконання. Приклад:@Deprecated

Джерело: Стара URL-адреса тепер мертва, і hunter_meta замінена на мисливець-мета-2-098036 . Якщо навіть це зменшиться, я завантажую зображення на сторінку.

Зображення (клацніть правою кнопкою миші та виберіть "Відкрити зображення в новій вкладці / вікні") Скріншот веб-сайту Oracle


1
спасибі за цитату, найцікавішим тут є випадок використання дляRetentionPolicy.CLASS
Макс

2
Ви можете пояснити, чому RetentionPolicy.class цікавий / напрочуд за замовчуванням?
sudocoder

1
@sudocoder - Перейдіть за цими посиланнями: stackoverflow.com/a/5971247/373861 та stackoverflow.com/a/3849602/373861 . Я вважаю, що ця конкретна політика потрібна для інструментарію байткодів. Хоча я ніколи його сам не використовував.
Фавоній

Наприкінці йдеться у наступній статті цієї серії, я покажу, як розширені можливості відображення Java, щоб допомогти вам виявити анотації під час виконання, і як інструмент обробки анотацій "підходить" дозволяє використовувати анотації під час збирання. , де ця стаття?
Сушант

@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()


Так, я теж так думав, але в класі, декомпільованому, нічого немає !!! і тому я плутаюсь ... Спробую перевірити файл класу інструментом
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?
Praveen Kamath

@PraveenKamath Я не знаю жодного прикладу, де вони корисні. Ймовірно, це трапляється лише в тому випадку, якщо ви робите речі JVM нижчого рівня, що більшість розробників ніколи не роблять. Повідомте мене, якщо ви знайдете заявку на них.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

5

Політика утримання: Політика зберігання визначає, в який момент відмітка відмічається. Він задається за допомогою вбудованих анотацій Java: @Retention[Про]

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
  • КЛАС : Анотації повинні записуватися у файл класу компілятором, але їх не потрібно зберігати VM під час виконання.
  • RUNTIME : Анотації повинні записуватися у файл класу компілятором і зберігати VM під час виконання, щоб вони могли читатися рефлекторно.
  • ДЖЕРЕЛЬ : Анотації повинні бути відкинуті компілятором.

Oracle Doc

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.