Аннотация vs Документационный комментарий
Прежде чем обсуждать, когда использовать аннотации вместо комментариев, важно сначала понять, что такое аннотации и для чего они используются в Java.
Аннотации не заменяют комментарии к документации (у них есть и другие применения), но во многих случаях (особенно в тех случаях, когда нам нужны аналогичные структурированные комментарии) они предпочтительнее комментариев. Причина в том, что аннотации являются типами в Java, как и любой другой тип данных, определяемый пользователем. И, следовательно, их можно использовать после того, как они определены.
Аннотации в Java на самом деле представляют собой всего лишь форму интерфейсов, и, следовательно, определение типа аннотации похоже на определение интерфейса. Ключевому слову «интерфейс» в определении аннотации предшествует символ «@».
Типичный комментарий к документации — это то, что обычно появляется в начале любого определения класса. Он содержит имя автора, версию, дату, дату последнего изменения и т. д. Итак, пример комментария будет выглядеть примерно так:
/**Author: Geek
*Version: 2.0
*Date: 6/16/2008
*Last Modified Date: 17/06/2024
*...
*...
*/
class ClassName{
...
}
С той же целью мы можем определить тип аннотации как:
@interface ClassHeaderAnnotation{
String author();
double version() default 1.0;
String date();
String lastModifiedDate();
......
}
После определения типа аннотации его можно использовать как:
@Documented // для ее включения в Javadoc
@ClassHeaderAnnotation(
author = "Geek",
version = "2.0", // можно оставить значение по умолчанию
date = "17/06/2024",
lastModifiedDate = "17/06/2024",
......
)
class ClassName{
...
}
Если мы хотим включить аннотацию в Javadoc, нам нужно аннотировать ее другой аннотацией под названием «@Documented».
Аннотация vs Маркерный интерфейс
Маркерный интерфейс — это интерфейс, который не содержит объявлений методов, а просто обозначает (или «маркирует») класс, реализующий этот интерфейс, как обладающий некоторым свойством. Например, рассмотрим интерфейс Serializable. Реализуя этот интерфейс, класс указывает, что его экземпляры могут быть записаны в ObjectOutputStream (или «сериализованы»).
Возможно, вы слышали, что аннотации делают маркерные интерфейсы устаревшими. Это утверждение неверно. Маркерные интерфейсы имеют два преимущества перед аннотациями. Прежде всего, интерфейсы определяют тип, который реализуется экземплярами отмеченного класса; аннотации этого не делают. Существование этого типа позволяет вам обнаруживать ошибки во время компиляции, которые вы не могли бы обнаружить до времени выполнения, если бы использовали аннотацию.
В случае маркерного интерфейса Serializable метод ObjectOutputStream.write(Object) завершится ошибкой, если его аргумент не реализует интерфейс. По необъяснимым причинам авторы API ObjectOutputStream не воспользовались преимуществами интерфейса Serializable при объявлении метода записи. Тип аргумента метода должен был быть Serializable, а не Object.
Еще одно преимущество маркерных интерфейсов перед аннотациями заключается в том, что их можно определить более точно. Если тип аннотации объявлен @Target(ElementType.TYPE), его можно применить к любому классу или интерфейсу. Предположим, у вас есть маркер, применимый только к реализациям определенного интерфейса. Если вы определите его как маркерный интерфейс, вы можете расширить единственный интерфейс, к которому он применим, гарантируя, что все отмеченные типы также являются подтипами единственного интерфейса.
Возможно, интерфейс Set является именно таким ограниченным маркерным интерфейсом. Он применим только к подтипам Collection, но не добавляет никаких методов, кроме тех, которые определены Collection. Обычно его не считают маркерным интерфейсом, поскольку он уточняет контракты нескольких методов Collection, включая .add(), .equals() и .hashCode(). Но легко представить маркерный интерфейс, применимый только к подтипам какого-то конкретного интерфейса и не уточняющий контракты любого из методов интерфейса как таковых.
Главное преимущество аннотаций перед маркерными интерфейсами заключается в том, что к типу аннотации можно добавить дополнительную информацию во время использования путем добавления одного или нескольких элементов аннотации со значениями по умолчанию. Такая возможность невозможна для маркерных интерфейсов, поскольку обычно невозможно добавлять методы к интерфейсу после его реализации.
Еще одним преимуществом аннотаций является то, что они являются частью более крупного средства аннотаций. Таким образом, они обеспечивают согласованность в средах, которые позволяют аннотировать различные элементы программы.