През 2005 г., с пристигането на Java 5, се запознахме с нови обекти, наречени анотации.

Анотациите са специална форма на синтактични метаданни, които могат да бъдат декларирани в code. Те се използват за анализиране на code по време на компилация or по време на изпълнение. Можете да мислите за анотация като етикет, таг or намек за компилатор.

Вероятно вече сте срещали анотации. Например, когато заместваме метод на родителския клас, пишем @Override преди самия метод. Тази анотация показва, че методът на родителя ще бъде заменен в дъщерния клас.

Синтаксис:

@Override
public int hashCode() {
      return super.hashCode();
}

Искам веднага да отбележа, че анотациите не се отнасят само за методи. Те се използват с пакети, класове, методи, полета и параметри.

За да разберем How работят анотациите, нека първо се запознаем с концепцията за маркерен интерфейс. От появата на Java, разработчиците винаги са имали нужда от начин за маркиране на класове, за да извършват определени действия върху тях.

Преди Java 5 те използваха интерфейс, който не правеше това, което очакваме интерфейсите да правят. Нямаше методи и договор. То просто маркира клас като специален по няHowъв начин.

Такъв интерфейс се нарича маркерен интерфейс. От името може да се досетите, че целта му е да маркира класове за JVM, компилатор or няHowва библиотека. Някои интерфейси на маркери, като Serializable , остават. Този маркерен интерфейс ни позволява да посочим, че екземплярите на даден клас могат да бъдат сериализирани.

Както видяхме, интерфейсите на маркерите продължават да съществуват дори след въвеждането на анотациите.

Анотации срещу интерфейси на маркери:

@MyAnnotation
public class MyClass {}
public class MyClass implements MarkerInterface {}

И двата подхода имат една и съща цел, но има ясна разлика в тяхното прилагане. Например, разгледайте интерфейс и анотация, която показва, че даден клас принадлежи към определен тип.

Ако използваме интерфейс, тогава маркираме класа. Ако го използваме неправилно и възникне грешка, тогава ще открием проблема при компorрането и програмата няма да стартира.

С поясненията всичко не е толкова просто: тук грешката ще бъде открита по време на изпълнение, което означава, че програмата ще започне, но не е изненадващо, че няма да завърши.

Имайте предвид, че ако трябва да маркираме клас за бъдеща употреба, неговите екземпляри трябва да бъдат предадени на конкретен метод:

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 Указва, че даден метод заменя метода на суперклас or имплементира метод на абстрактен клас or интерфейс.
@Override
public int hashCode() {
        return super.hashCode();
}
@Отхвърлено Маркира codeа като остарял.
@Deprecated
public abstract void method();
@SuppressWarnings Деактивира предупрежденията на компилатора за анотирания елемент. Имайте предвид, че ако трябва да деактивирате няколко категории предупреждения, те трябва да бъдат затворени във фигурни скоби, например @SuppressWarnings({"unchecked", "cast"}) .
public class DocumentsFolder {
   private List documents;

   @SuppressWarnings("unchecked")
public void addDocument(String document) {
            documents.add(document);
   }
}

В този пример се опитваме да добавим към списък, който няма дефиниран тип (генеричен тип). Компилаторът ще ни предупреди за това. Това е много полезно, но понякога има твърде много "предупреждения" и те могат да бъдат шумни. Можете да използвате тази анотация на метода и да посочите тип предупреждение на компилатора като аргумент. Има много маркери, така че не се притеснявайте да ги запомните всички — IDEA обикновено ще ви каже кой да добавите.

Друг пример с множество аргументи:

@SuppressWarnings({"unchecked", "deprecated"})