В 2005 году с приходом версии Java 5 нам стали известны новые сущности под названием аннотации.
Аннотации — это особая форма синтаксических метаданных, которые можно объявить в коде. Они используются для анализа кода при компиляции или во время выполнения программы. Аннотацию можно сравнить с меткой, маркером или указанием для компилятора.
Ты наверняка уже сталкивался с аннотациями. Например, при переопределении метода родительского класса перед самим методом мы пишем @Override. Это и есть аннотация, которая указывает на то, что родительский метод будет переопределен в классе-наследнике.
Синтаксис:
@Override
public int hashCode() {
return super.hashCode();
}
Сразу хочу отметить, что аннотации применимы не только к методам, ведь они используются в сочетании с пакетами, классами, методами, полями и параметрами.
Для понимания работы аннотаций сначала познакомимся с понятием маркерного интерфейса. Необходимость помечать определенным образом класс для выполнения над ним тех или иных действий существовала у Java-разработчиков с момента появления языка.
До Java 5 для этого использовали интерфейс, не похожий даже сам на себя и не соответствующий своему предназначению. Он был без методов, не нес за собой никакого контракта, просто помечал класс для обособления.
Такой интерфейс назывался маркерным. Из названия следует, что его задача — это маркировать классы для JVM, компилятора или какой-либо библиотеки. До сих пор остались некоторые маркерные интерфейсы, например, Serializable. Этот маркер позволяет нам пометить класс, сообщая о том, что его экземпляры можно сериализовать.
Мы убедились, что использование маркерных интерфейсов продолжает жить даже после появления аннотаций.
Эквивалентное использование аннотации и маркерного интерфейса:
@MyAnnotation
public class MyClass {}
public class MyClass implements MarkerInterface {}
Несмотря на то, что задача у обоих подходов одна и та же, есть явная разница в их реализации. Для примера рассмотрим интерфейс и аннотацию для определения принадлежности класса к определенному виду.
В случае с интерфейсом мы помечаем класс: даже при неправильном использовании и появлении ошибки она выявится на этапе компиляции и программа не будет запущена.
С аннотациями не все так просто: ошибка выявится уже в рантайме, а это значит, что программа начнет выполнение, но, ожидаемо, не закончит.
Следует отметить, что если нам нужно пометить класс для возможности использования в дальнейшем, его экземпляры надо передавать в определенный метод:
public class MyInteger implements Sum {}
interface Sum {};
public static void main(String[] args) throws IOException {
increase(new MyInteger());
}
public static void increase(Sum count) {
// TODO
}
Лучше всего здесь подойдет маркерный интерфейс.
Аннотации лучше использовать, когда есть необходимость в чем-то большем, например, в параметрах, которые аннотация позволяет передать.
Давай рассмотрим стандартные аннотации в JDK:
Аннотация | Описание | Пример |
---|---|---|
@Override | Указывает, что метод переопределяет метод суперкласса или реализует метод абстрактного класса или интерфейса. |
|
@Deprecated | Помечает код как устаревший. |
|
@SuppressWarnings | Отключает для аннотированного элемента предупреждения компилятора. Обрати внимание: если необходимо отключить несколько категорий предупреждений, их следует добавить в фигурные скобки, например, @SuppressWarnings ({"unchecked", "cast"}). |
В этом примере мы пытаемся в методе добавить в список, у которого не определен тип (дженерик). Компилятор предупредит нас об этом. Хоть это и очень полезно, иногда “ворнингов” бывает слишком много, и они очень шумные. В этом случае можно использовать данную аннотацию к методу с указанием параметра-маркера предупреждения компилятора. Маркеров существует очень много,так что необязательно помнить все, обычно IDEA сама подскажет, какой поставить. Еще пример использования с передаваемыми несколькими параметрами:
|
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ