Java Basics: Аннотации

Аннотации

Для параметров значения по умолчанию, default, могут быть только константы и не null значения. Любое значение, которое не может быть вычислено на этапе компиляции будет провоцировать ошибку компиляции:

1
2
3
4
5
6
7
public @interface Iface {
String name() default "A";
Integer count() default null; // ошибка компиляции
String address() default new String("B"); // ошибка компиляции
Integer log() default 1;
int scale() default 1+2;
}

В качестве параметров допускается использование только:

  • Примитивы (int, double и т.д.). Классы-обертки использовать запрещено!
  • Строки (только вычисленные на момент компиляции)
  • Объекты типа Class
  • enum
  • Другие аннотации
  • Массивы (типа int[], String[] и т.д.), но не многоуровневые массивы типа (int[][], String[][])

Константы в аннотациях

Допускается. Тогда модификаторы у них будут public static final (как у интерфейсов):

1
2
3
4
public @interface Iface {
int MAX = 1;
public static final int MIN = 1;
}

Области применения аннотаций

Допускается к применению с:

  • Классы, интерфейсы, enum, модули;
  • Переменные (static, instance, local);
  • Методы и конструкторы; так же, любые их параметры;
  • Другие аннотации;
  • Наложение аннотаций при type-cast:
1
2
3
4
@Food(vegeterian=true) String fruit = (@Delicious(type="sweat") String) "mango";

Something x = new @CustomThing(1) Something(){};
Supplier<String> y = (@CustomThing(2) @Test String in) -> in.toUpperCase();

@Target

Ограничивает область применения аннотации. Принимает объект ElementType следующих типов:

  • TYPE - class, interface, enum, @interface;
  • FIELD - параметры класса, статические переменные, значения в enum;
  • METHOD - методы (только);
  • PARAMETER - параметры методов, конструкторов и лямбд;
  • CONSTRUCTOR - только конструкторы;
  • PACKAGE - аннотации на пакет;
  • TYPE_PARAMETER - параметризованные типы, ;
  • MODULE - модули;
  • ANNOTATION_TYPE - где угодно, где может участвовать Java тип. Может быть довольно противоречивым;
  • LOCAL_VARIABLE - аннотация доступа только на этапе компиляции. В runtime не будет найдена и прочитана.

@Retention

Ограничение на момент жизни аннотации:

  • SOURCE - доступна только в исходном коде. При компиляции будет удалена;
  • CLASS - хранится в скомпилированном *.class, но в момент выполнения программы недоступна;
  • RUNTIME - доступна всегда. По умолчанию.

SOURCE следует использовать если аннотируемая реализация фактически не будет использована и следует ее расширять, или как какой-нибудь маркер; CLASS используется для учета классов, аннотированных чем-либо; RUNTIME - стандартные случаи.

@Documented

Требует ведения JavaDoc для структур языка - class, interface, enum или @interface.

@Inherited

Указывает что наследуемые (дочерние) классы будут полностью перенимать все свойства данной аннотации:

1
2
3
4
5
6
7
@Inherited
public @interface X{}

@X
public class Parent {}

public class Child {} // будет аннотирован @X

@Repeatable

Позволяет присваивать несколько одинаковых аннотаций одному объекту.

1
2
3
4
5
6
7
@Repeatable
public @interface MultipleAnnotations {}

@MultipleAnnotations
@MultipleAnnotations
@MultipleAnnotations
public class AnnotatedClass {}

Старый способ добавления нескольких аннотаций так же допустим, но не рекомендуется:

1
2
3
4
5
6
7
8
9
10
11
12
public @interface AnnotationsContainer {
MultipleAnnotations[] value();
}

public @interface MultipleAnnotations {}

@AnnotationContainer({
@MultipleAnnotations
@MultipleAnnotations
@MultipleAnnotations
})
public class AnnotatedClass {}

@Override

Накладывается на метод и требует ту же сигнатуру, тот же модификатор доступа (без него метод может расширить его), совместимый тип результата, отсутствие checked исключений, которого нет у родительского метода.

Метод будет де-факто, итак перезаписан, если все вышеуказанные условия сохранятся, но в случае малейшего расхождения, компилятором будет выдана ошибка.

@Deprecated

Позволяет добавлять предупреждения (warning), указываемые компилятором. В случае установки, рекомендуется в JavaDoc указывать причину и версию, начиная с которой использование будет прекращено.

1
2
3
4
5
6
7
8
9
/**
* Method description
* @deprecated method replacement recomendations
*/
@Deprecated(since="2000-01-01", forRemoval=true)
public void someMethod();

@Deprecated(since="v12.1.3", forRemoval=false)
public void someMethod();

@SuppressWarnings

Отключает предупреждения (warning) компилятора для класса, метода, переменной и т.д. Используя определенные модификаторы для отключения того или иного типа предупреждения:

  • All - отключить все;
  • Boxing - приведение к примитивам;
  • Cast - type-cast;
  • Deprecation - игнорирование @Deprecated;
  • Null
  • Rawtypes - не параметризованные типы;
  • Serial - отсутствие serialVersionUID для Serializable;
  • Static-method - метод со статичным доступом;
  • Super - переписывание операции;
  • Unchecked - непроверенные операции;
  • Unused - “мертвый” код - неиспользуемый.
1
2
@SuppressWarnings({"cast", "serial"})
public class SomeClass {}

@SafeVarargs

Аннотация убирает предупреждения по возможному некорректному использованию varargs атрибута и сигнализирует компилятору, что для внешних методов varargs безопасны, а их обработку без ошибок берет на себя сам метод.

Так происходит когда компилятор указывает внешним методам на небезопасный type-cast. Аннотация применима только к методам, которые могут быть переписаны и у которых есть varargs:

1
2
@SafeVarargs
public void unsafe(Integer ... i) {}
 Comments
Comment plugin failed to load
Loading comment plugin