Аннотации Java  -  основы

Если вы когда-либо видели кодовую базу Java, есть большая вероятность, что вы видели и что-то вроде @Override или подобного перед методом или классом. Такие тэги называются аннотациями. Аннотации  —  это тэги метаданных, которые помогают определить дополнительную информацию для классов, интерфейсов, методов или полей. Аннотации не добавляют дополнительной реализации к функциональному коду, но помогают с необязательной информацией, такой как:

  • Информация для компилятора. Компилятор может использовать аннотации для обнаружения ошибок или подавления предупреждений.
  • Информация для разработчика. Когда кто-то просматривает код, аннотации помогают сделать его читабельным и более легким для понимания.
  • Обработка времени компиляции и развертывания. Программные средства могут обрабатывать аннотации для создания кода, XML-файлов и т.д.
  • Обработка во время выполнения. Аннотации могут проверяться во время выполнения для прохождения тестов.

Java содержит целый набор предопределенных аннотаций и даже позволяет определять свои собственные. Ниже приведем список наиболее широко распространенных и важных аннотаций.

Предопределенные аннотации

@Override

Аннотация @Override сообщает компилятору, что элемент подкласса переопределяет элемент родительского класса или суперкласса. Хотя эта аннотация не обязательна при переопределении метода, она помогает предотвратить ошибки. Если метод, помеченный как “override”, не может правильно переопределить метод суперкласса, компилятор выдает ошибку.

class Avatar {    
public void destroyEvil() { ... }          // переопределенный
}

class Aang extends Avatar {     
@Override                                   
// overriding method
    public void destroyEvil() { ... }
}

@SuppressWarnings

Предупреждения компилятора полезны, если вы их читаете, но они часто создают “шум” в терминале. @SuppressWarnings будет подавлять эти предупреждения. Компилятор Java может выдавать множество предупреждений, но с помощью @SuppressWarnings вы можете скрыть все предупреждения или выбрать предупреждения, появления которых вам хочется избежать.

@SuppressWarnings({“unchecked”, “deprecated”}) будет скрывать предупреждения о непроверенных (unchecked) и устаревших (deprecated) методах.

@SuppressWarnings("unchecked")
void uncheckedWarning() {
List words = new ArrayList();
words.add("hello"); //выбрасывает предупреждение о непроверенном
}

@deprecated

Обозначение @deprecated также очень распространено. Это означает, что аннотированный метод устарел и больше не поддерживается разработчиками. Компилятор не будет обрабатывать устаревший метод иначе, чем обычный метод. Таким образом, даже если метод допустимо вызвать, возвращаемый им ответ может быть не идеальным. Это документация для разработчиков.

@depricated
public String prepareForY2K() { ... }

@author

Тэг @author  —  простая аннотация, документирующая автора метода или файла. Обычно соединяется с некоторой дополнительной информацией, такой как версия, номер релиза и т.д.

Oracle рекомендует писать тэги в следующем порядке:

  • @author  —  документирует автора кода;
  • @version —  обеспечивает только одно обновление за раз (позволяет избежать блокировки);
  • @param —  документирует имя и описание параметров;
  • @return  —  документирует возвращаемое значение; опускать, если возвращает пустоту (void);
  • @throws  —  документирует проверенные исключения (объявленные в throws);
  • @see  —  ссылка или указание на ссылку;
  • @since  —  документирует версию продукта, с которой была добавлена новая функциональность;
  • @deprecated  —  документирует, что код больше не поддерживается.

Тест-аннотации

Написание тестов  —  важнейший аспект цикла разработки и так же (если не более) важно, как и написание самой кодовой базы. Существуют различные аннотации, созданные явно для тестов.

@Test

@Test сообщает JUnit, что аннотированный метод должен выполняться как тест. Чтобы запустить метод, JUnit создает новый экземпляр класса, а затем вызывает тестовый метод.

Для этой аннотации можно указать два необязательных параметра:

@Timeout приводит к сбою метода тестирования, если выполнение занимает больше времени, чем указанное время, измеренное на часах в миллисекундах.

Например, следующий тест упадет (через 0,1 секунды):

@Test(timeout=100)
public void toInfinityAndBeyond() {
while(true);
}

@Expected объявляет, что тестовый метод должен выдавать определенное исключение, в противном случае тест завершится неудачей.

Например, в примере ниже произойдет сбой:

@Test(expected=NullPointerException.class)
public void outOfBounds(){
new ArrayList<Object>().get(1);
}

@Ignore

Аннотация @Ignore указывает игнорировать тест или группу тестов, чтобы избежать потенциального сбоя при выполнении.

Игнорировать тесты можно в двух сценариях:

  • игнорировать тестовый метод, помеченный @Test.
  • игнорировать все тесты на уровне класса.
@Ignore
@Test(expected=NullPointerException.class) //obviously wrong test
public void outOfBounds(){

new ArrayList<Object>().get(1);
}

@Before

Методы, помеченные тэгом @Before, выполняются перед каждым тестом. Это полезно, когда вы хотите выполнить некоторый код перед запуском теста, например, настроить тестовую среду. В Junit5 @Before был переименован в @beforeEach, что также работает.

Родственная аннотация @beforeAll или @BeforeClass используется, когда перед серией тестов необходимо выполнить дорогостоящую операцию, такую как запуск сервера или внесение изменений в базу данных.

@After

@After  —  это противоположность предыдущему тэгу. Все методы, помеченные @After, будут запущены после теста.

Методы @AfterAll или @AfterClass выполняются после выполнения всех тестов класса.

Все методы, аннотированные @beforeAll и @afterAll должны быть статическими, так как выполняются перед запуском тестов класса.

Однако методы @Before и @After не должны быть статическими, иначе компилятор выдаст ошибку.

public class OutputFileTest{    @BeforeAll
    public static void startServer() { ... }    

    @Before	
    public void createTestLogFile() { ... }
  
    @After
    public void deleteTestLogFile() { ... }
     
    @Test 
    public void test1() { ... }    

    @Test 
    public void test2() { ... }    

    @AfterAll
    public static void stopServer() { ... }
}

Код, приведенный выше, выполнится в следующем порядке:

🟢 0️⃣ startServer() 1️⃣ createTestLogFile() 2️⃣ test1() 3️⃣ deleteTestLogFile()4️⃣ createTestLogFile() 5️⃣ test2() 6️⃣ deleteTestLogFile() 7️⃣stopServer()🔴

Этот список далеко не исчерпывающий, но он охватывает самые основные аннотации. Воспользуйтесь приведенными выше примерами, чтобы получить представление о лучших практиках в программировании на Java.

Читайте также:

Читайте нас в TelegramVK и Яндекс.Дзен


Перевод статьи: Utkarsh Jain, “Java Annotations 101”

Предыдущая статьяPHP: массивы
Следующая статьяMongoDB: агрегирование