Какая причина для java.lang.annotation.Retention?
Мне хорошо известно о значении RetentionPolicy
и знаю, что они делают, и когда он имеет смысл использовать их. Для моей собственной аннотации я точно знаю, нужны ли они во время выполнения, в файлах классов или просто для компиляции. Однако с любой аннотацией, определенной в библиотеке, вы можете ИМХО никогда не быть уверенным.
Например, javax.annotation.Generated
предназначен для обозначения сгенерированного кода, но он редко бывает полезен. Поскольку AFAIK больше инструментов, работающих с байт-кодом, чем инструменты, работающие с источником, информация исчезает непосредственно перед ее использованием.
Поскольку аннотации, отсутствующие во время выполнения не выбрасывают ClassNotFoundException
(в отличие, например, от недостающих интерфейсов), использование RetentionPolicy.RUNTIME
, по-видимому, не наносит вреда. Или я не прав?
Или было сохранение нескольких байтов причиной использования разных Retention
s? Для меня, похоже, слишком много проблем стоит того. Что мне не хватает?
Ответы
Ответ 1
Вдохновение для аннотаций Java произошло до 2002 года, в результате перехода от Java 1.3 к Java 1.4. В те времена настольный компьютер с высокими спецификациями был Pentium 4 с частотой около 2,5 ГГц или Athlon XP + с частотой около 2 ГГц, оперативной памятью было бы 256 или 512 МБ. Например, здесь.
Проблема заключалась в том, как хранить и извлекать метаданные о коде. Типичным решением было использование XML файлов, которые не были проверены типом или напрямую связаны с исходным кодом. Другие уже неформально расширяли JavaDoc (исходный код и API расширения присутствовали в JDK) для инструментов генерации кода. Решение, аннотации, это взломать (довольно неплохо взломать), который расширил Javadoc и спецификацию класса JLS.
Понятно, что оригинальные авторы были обеспокоены производительностью (а в 2002 году Java все еще была относительно медленной, очень медленной, и время выполнения Java было огромным болотом памяти, некоторые вещи никогда не меняются). Это из введения к JSR-175:
Поскольку многие аннотации будут использоваться только средствами разработки, такими как генераторов-заглушек, нет смысла сохранять все аннотации в время выполнения; это может увеличить временную память - след и вред представление. Однако существуют некоторые типы аннотаций, которые полезны во время выполнения и некоторые из них, которые полезны в инструментах, которые имеют доступ только к файлам классов (а не к исходным файлам). Поэтому некоторые аннотации хранится компилятором в атрибутах файла класса (JVMS 4.7), а некоторые эти аннотации затем становятся доступными для проверки во время выполнения через новые отражающие API.
Их решение проблемы состояло в том, чтобы разделить проблему на три варианта:
VI. Чтение аннотаций
Пользователи аннотации могут быть разделены на три группы:
а. "Интроспекторы" - программы, которые запрашивают видимые во времени аннотации их собственные программные элементы. Эти программы будут загружать как аннотированные классов и аннотаций в виртуальную машину. (От время видимости, мы имеем в виду аннотации, сохранение которых политика RUNTIME.)
б. "Специальные инструменты" - программы, которые запрашивают известные типы аннотаций произвольных внешних программ. Шунтовые генераторы для например, попадают в эту категорию. Эти программы будут читать аннотированные классов, не загружая их в виртуальную машину, но загружает интерфейсы аннотации.
с. "Общие инструменты" - программы, которые запрашивают произвольные аннотации произвольных внешних программ (таких как компиляторы, генераторы документации и браузеры классов). Эти программы не будут загружать ни аннотированные классы, ни аннотационные интерфейсы в виртуальную машину. Говорят, что такие программы действуют "на длина".
Это позволило (в то время) значительным вариантам использования "конкретных инструментов" и "общих инструментов", как определено выше, сделать свою работу, не создавая нагрузки на время выполнения; Для этих инструментов аннотации могут быть либо ИСТОЧНИКОМ, либо КЛАССОМ. В JVM были загружены и сохранены только аннотации, которые были необходимы во время выполнения (из вышеизложенного, ясно, что это считается вариантом использования меньшинства).
Итак, да, политика хранения была введена в действие, чтобы сохранить байты и накладные расходы времени исполнения. Хотя сейчас это выглядит странно, 2002 год был другим миром, а память и производительность были очень реальными проблемами. Теперь у нас есть 10-кратная производительность и память, вы можете безопасно использовать удержание RUNTIME без проблем.
Ответ 2
Например, javax.annotation.Generated предназначен для обозначения сгенерированных кода, но это редко полезно. Поскольку AFAIK больше инструментов, работающих на байт-код, чем инструменты, работающие с источником, информация исчезает непосредственно перед тем, как он может быть использован.
Взгляните на редактор исходного кода, Android Studio, полученный из JetBrains и многих других IDE, нужно работать с исходным кодом, и он предоставляет все великолепные возможности редактирования только из-за компиляции аннотаций времени.
Пока класс редактируется (еще не скомпилирован), редактор может хранить и обрабатывать аннотации.
Пример:
@SuppressWarnings
позволяет вам подавлять предупреждения, как еще вы могли это сделать? С# позволяет определить #PRAGMA
, #IF
, некоторую условную компиляцию. Ни одна из данных условной компиляции не сохраняется в скомпилированном виде.
@Override
позволяет компилятору Java проверять, есть ли у базового класса метод переопределения или нет, если вы определяете новый метод с ошибочными параметрами, java-компилятор будет компилировать класс с новым методом с перегрузкой, но в присутствии @Override
java компилятор даст вам ошибку, которая не соответствует правилу, чтобы переопределить метод.
@GeneratedCode
позволяет IDE пропускать классы и элементы, которые будут отображаться при поиске с помощью "Найти и заменить", и позволяет вам работать с IDE только на вашем коде, а не на сгенерированном. Вы видели R.*
для ресурсов в Android, эти сгенерированные классы скрыты в Android Studio, но они предоставляют полезные списки завершения кода.
Подобным образом многие такие аннотации позволяют выполнять анализ кода, записывать единичные тесты и т.д. и выполнять большую работу с ним перед компиляцией.
Подробнее
Многие структуры ORM используют компиляцию аннотаций времени и генерируют полезные дополнительные классы, используемые для типизированных запросов и других вспомогательных классов для создания таблиц и поддержания схемы.
Заключение
В приведенном выше примере ясно, что все три и многие подобные аннотации не будут лишними, добавьте столько байтов, которые во время выполнения полностью бесполезны.
В Java было два варианта: один добавлял аннотацию времени компиляции с использованием директив #IF
etc, используемых на языке c. Для чего потребуется новый синтаксис и новый опыт редактирования и т.д., А другой - создание Retention
. Было приятным движением для создания Retention
без нарушения синтаксиса.
Ответ 3
Основная цель аннотаций - перенос метаданных для единицы компиляции. Большинство стандартных аннотаций четко выражают метаинформацию, которая помогает в разработке и компиляции кода (путем указания свойств, которые могут быть разрешены с помощью IDE или компилятора).
Аннотации не предназначены для изменения семантики языка выполнения. Таким образом, независимо от того, доступна ли аннотация или нет во время выполнения, само по себе не выполняется исполнение. (Конечно, если вы активно используете метаинформацию для настройки поведения реализации, тогда все возможно.)
Если в библиотечном банке где-то аннотация помечена как RetentionPolicy.RUNTIME
, очевидно, что доступ к аннотации из среды выполнения (с использованием отражения) полезен для более поздних пользователей.
Если в то же время реализация аннотации из другой библиотеки, то такое ожидание либо не является оправданным, либо связано с конкретной целью этой аннотации, которая может быть полезна только для определенных случаев использования. (И создание различных версий jar только для разных настроек удержания наверняка не подходит.)
Таким образом, если разработчик отмечает аннотацию как RetentionPolicy.RUNTIME
, в явном виде понимается, где ожидается доступ к рабочему столу. Вне зависимости от того, реализована ли реализация аннотации одной и той же банкой или другой, может быть независимой от варианта использования (например, на основе других критериев структурирования). В любом случае, если вы намереваетесь извлечь выгоду из этого варианта использования, у вас будет эта библиотека аннотаций в вашем пути к классу (так как вам могут понадобиться другие компоненты), и все в порядке. если вы не применитесь к этому прецеденту, тогда вам не повлияет на отсутствие реализации аннотации.
Переписка по вашему вопросу:
использование RUNTIME
удержания не наносит вреда программе, кроме загромождения (байт-кода) исполняемых файлов с мертвой информацией. Использование хранения RUNTIME
только в том случае, когда ожидаемая (и считается полезной) использование метаинформации во время исполнения добавляет к качеству кода (с точки зрения ремонтопригодности и понятности).
Ответ 4
@Retention
Эта аннотация указывает, как помеченная аннотация хранится в java-среде выполнения. Является ли он ограничен только исходным кодом, встроенным в сгенерированный файл класса, или он будет доступен во время выполнения через отражение.
таким образом Указывает, как долго аннотации с аннотированным типом должны быть сохранены. Если в объявлении типа аннотации нет аннотации Retention, политика хранения по умолчанию имеет значение RetentionPolicy.CLASS.
Политика хранения определяет, в какой момент аннотация должна быть отброшена.
Java определила три типа политик хранения через java.lang.annotation.RetentionPolicy перечисление. У него есть ИСТОЧНИК, КЛАСС и RUNTIME.
Аннотации с политикой хранения SOURCE будут сохранены только с исходным кодом и будут отброшены во время компиляции.
Аннотации с политикой хранения CLASS сохраняются до компиляции кода и отбрасываются во время выполнения.
Аннотации с политикой хранения RUNTIME будут доступны для JVM через время выполнения.
Политика хранения будет указана с помощью встроенной аннотации @Retention в java, и мы должны передать тип политики хранения.
Тип политики хранения по умолчанию - CLASS.