Suppresswarnings java что это
Указывает, что именованные предупреждения компилятора должны быть подавлены в аннотируемом элементе (и во всех элементах программы, содержавшихся в аннотируемом элементе). Отметьте, что набор предупреждений, подавленных в данном элементе, является надмножеством предупреждений, подавленных во всем содержащем элементы. Например, если Вы аннотируете класс, чтобы подавить предупреждение того и аннотировать метод, чтобы подавить другого, то оба предупреждения будут подавлены в методе. Как стиль, программисты должны всегда использовать эту аннотацию на наиболее глубоко вложенный элемент, где это эффективно. Если Вы хотите подавить предупреждение в определенном методе, следует аннотировать тот метод, а не его класс.
Необходимая Сводка Элемента
| Модификатор и Тип | Необходимый Элемент и Описание |
|---|---|
| Строка[] | значение |
Набор предупреждений, которые должны быть подавлены компилятором в аннотируемом элементе.
Деталь элемента
значение
public abstract String[] value
Набор предупреждений, которые должны быть подавлены компилятором в аннотируемом элементе. Двойные названия разрешаются. Вторые и последовательные возникновения имени игнорируются. Присутствие нераспознанных имен предупреждения не является ошибкой: Компиляторы должны проигнорировать любые имена предупреждения, которые они не распознают. Они, однако, свободны испустить предупреждение, если аннотация содержит нераспознанное имя предупреждения. Поставщики компилятора должны задокументировать имена предупреждения, которые они поддерживают в соединении с этим типом аннотации. Они поощряются сотрудничать, чтобы гарантировать, что те же самые имена работают через многократные компиляторы.
Платформа Java™
Стандарт Эд. 7
Представьте ошибку или функцию
Для дальнейшей ссылки API и документации разработчика, см. Java Документация SE . Та документация содержит более подробные, предназначенные разработчиком описания, с концептуальными краткими обзорами, определениями сроков, обходных решений, и рабочих примеров кода.
Авторское право © 1993, 2011, Oracle и/или его филиалы. Все права защищены.
Suppresswarnings java что это
Пожалуйста, учтите, что спецификации и другая информация, содержащаяся здесь, не являются заключительными и могут быть изменены. Информация доступна для вас исключительно ради ознакомления.
Платформа Java™
Стандарт Эд. 8
Проект сборка-b92
- Сводка:
- Требуемый |
- Дополнительный
- Детально:
- Элемент
Тип аннотации SuppressWarnings
@Target(value=TYPE,FIELD,METHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE>) @Retention(value=SOURCE) public @interface SuppressWarnings
Указывает, что именованные предупреждения компилятора должны быть подавлены в аннотируемом элементе (и во всех элементах программы, содержавшихся в аннотируемом элементе). Отметьте, что набор предупреждений, подавленных в данном элементе, является надмножеством предупреждений, подавленных во всем содержащем элементы. Например, если Вы аннотируете class, чтобы подавить предупреждение того и аннотировать метод, чтобы подавить другого, то оба предупреждения будут подавлены в методе. Как стиль, программисты должны всегда использовать эту аннотацию на наиболее глубоко вложенный элемент, где это эффективно. Если Вы хотите подавить предупреждение в определенном методе, следует аннотировать тот метод, а не его class.
Необходимая Сводка Элемента
| Модификатор и Тип | Необходимый Элемент и Описание |
|---|---|
| Строка[] | значение |
Набор предупреждений, которые должны быть подавлены компилятором в аннотируемом элементе.
Деталь элемента
значение
public abstract String[] value
Набор предупреждений, которые должны быть подавлены компилятором в аннотируемом элементе. Двойные названия разрешаются. Вторые и последовательные возникновения имени игнорируются. Присутствие нераспознанных имен предупреждения не является ошибкой: Компиляторы должны проигнорировать любые имена предупреждения, которые они не распознают. Они, однако, свободны испустить предупреждение, если аннотация содержит нераспознанное имя предупреждения. Строка «unchecked» используется, чтобы подавить предупреждения непроверенные. Поставщики компилятора должны задокументировать дополнительные имена предупреждения, которые они поддерживают в соединении с этим типом аннотации. Они поощряются сотрудничать, чтобы гарантировать, что те же самые имена работают через многократные компиляторы.
Платформа Java™
Стандарт Эд. 8
Проект сборка-b92
- Сводка:
- Требуемый |
- Дополнительный
- Детально:
- Элемент
Представьте ошибку или функцию
Для дальнейшей ссылки API и документации разработчика, см. Java Документация SE. Та документация содержит более подробные, предназначенные разработчиком описания, с концептуальными краткими обзорами, определениями сроков, обходных решений, и рабочих примеров кода.
Авторское право © 1993, 2013, Oracle и/или его филиалы. Все права защищены.
Проект сборка-b92
Аннотации в Java и их обработка

Аннотация — это специальная конструкция языка, связанная с классом, методом или переменной, предоставляющая программе дополнительную информацию, на основе которой программа может предпринять дальнейшие действия или реализовать дополнительную функциональность, такую как генерация кода, проверка ошибок и т. д.
Помимо использования стандартных аннотаций из пакета java.lang, о которых мы поговорим далее, можно также создавать свои аннотации и обрабатывать их.
В этой статье мы обсудим назначение стандартных аннотаций, а также рассмотрим на практическом примере создание и обработку своих аннотаций.
Код примеров вы можете найти на GitHub.
Основы аннотаций
Аннотации начинаются с символа @ . Например, в пакете java.lang определены аннотации @Override и @SuppressWarnings .
Сама по себе аннотация не выполняет никаких действий. Она просто предоставляет информацию, которую можно использовать во время компиляции или в рантайме.
В качестве примера рассмотрим аннотацию @Override :
public class ParentClass < public String getName() > public class ChildClass extends ParentClass < @Override public String getname() >
Аннотация @Override используется для обозначения переопределенного метода из базового класса. Приведенная выше программа при компиляции выдаст ошибку, потому что метод getname() в классе ChildClass аннотирован @Override , но в родительском классе ParentClass метода getname() нет.
Используя аннотацию @Override в ChildClass , компилятор проверяет, что имя переопределенного метода в дочернем классе совпадает с именем метода в родительском классе.
Стандартные аннотации
Рассмотрим некоторые из распространенных стандартных аннотаций из пакета java.lang . Чтобы увидеть их влияние на поведение компилятора, запускайте примеры из командной строки, поскольку большинство IDE могут подавлять предупреждения.
@SuppressWarnings
Аннотация @SuppressWarnings используется для подавления предупреждений компилятора. Например, @SuppressWarnings («unchecked») отключает предупреждения, связанные с «сырыми» типами (Raw Types).
Давайте рассмотрим пример использования @SuppressWarnings :
public class SuppressWarningsDemo < public static void main(String[] args) < SuppressWarningsDemo swDemo = new SuppressWarningsDemo(); swDemo.testSuppressWarning(); >public void testSuppressWarning() < Map testMap = new HashMap(); testMap.put(1, "Item_1"); testMap.put(2, "Item_2"); testMap.put(3, "Item_3"); >>
Если мы запустим компиляцию из командной строки с параметром -Xlint:unchecked , то получим следующее сообщение:
javac -Xlint:unchecked ./com/reflectoring/SuppressWarningsDemo.java Warning: unchecked call to put(K,V) as a member of the raw type Map
Это пример легаси кода (до Java 5) — в коллекции мы можем случайно сохранить объекты разных типов. Для проверки подобных ошибок на этапе компиляции, были придуманы обобщенные типы (generics, дженерики). Чтобы этот код компилировался без предупреждений измените строку:
Map testMap = new HashMap();
Map testMap = new HashMap<>();
Если подобного легаси кода много, то вы вряд ли захотите вносить изменения, поскольку это влечет за собой много регрессионного тестирования. В этом случае к классу можно добавить аннотацию @SuppressWarning , чтобы логи не загромождались избыточными предупреждениями.
@SuppressWarnings() public class SuppressWarningsDemo
Теперь при компиляции предупреждений не будет.
@Deprecated
Аннотация @Deprecated используется для пометки устаревших методов или типов.
IDE автоматически обрабатывают эту аннотацию и обычно отображают устаревший метод зачеркнутым шрифтом, сообщая разработчику, что больше не следует его использовать.
В примере ниже метод testLegacyFunction() помечен как устаревший:
public class DeprecatedDemo < @Deprecated(since = "4.5", forRemoval = true) public void testLegacyFunction() < System.out.println("This is a legacy function"); >>
В атрибуте since этой аннотации содержится версия, с которой элемент объявлен устаревшим, а forRemoval указывает, будет ли элемент удален в следующей версии.
Теперь вызов устаревшего метода, вызовет предупреждение во время компиляции, указывая, что лучше этот метод не использовать:
./com/reflectoring/DeprecatedDemoTest.java:8: warning: [removal] testLegacyFunction() in DeprecatedDemo has been deprecated and marked for removal demo.testLegacyFunction(); ^ 1 warning
@Override
Мы уже упоминали выше аннотацию @Override . Она используется для проверки переопределенных методов во время компиляции на такие ошибки, как опечатки в регистре символов:
public class Employee < public void getEmployeeStatus()< System.out.println("This is the Base Employee class"); >> public class Manager extends Employee < public void getemployeeStatus()< System.out.println("This is the Manager class"); >>
Здесь мы хотели переопределить метод getEmployeeStatus() , но неправильно написали имя метода. Это может привести к серьезным ошибкам. Приведенная выше программа скомпилируется и запуститься без проблем, не обнаружив эту ошибку при компиляции.
Если добавить аннотацию @Override к методу getemployeeStatus() , то при компиляции получим следующую ошибку:
./com/reflectoring/Manager.java:5: error: method does not override or implement a method from a supertype @Override ^ 1 error
@FunctionalInterface
Аннотация @FunctionalInterface используется для указания того, что в интерфейсе не может быть более одного абстрактного метода. Если абстрактных методов будет больше одного, то компилятор выдаст ошибку. Функциональные интерфейсы появились в Java 8 для реализации лямбда-выражений и гарантии того, что в них не более одного абстрактного метода.
Но и без аннотации @FunctionalInterface компилятор выдаст ошибку, если вы включите в интерфейс больше одного абстрактного метода. Так зачем же нужна необязательная аннотация @FunctionalInterface ?
Давайте рассмотрим следующий пример:
@FunctionalInterface interface Print
Если в интерфейс Print мы добавим еще один метод printString2() , то компилятор или IDE выдаст ошибку.
А что, если интерфейс Print находится в отдельном модуле и без аннотации @FunctionalInterface ? Разработчики этого модуля могут легко добавить в интерфейс еще один метод и сломать ваш код. Добавив аннотацию @FunctionalInterface , мы сразу получим предупреждение в IDE:
Multiple non-overriding abstract methods found in interface com.reflectoring.Print
Поэтому рекомендуется всегда использовать аннотацию @FunctionalInterface , если интерфейс должен использоваться в качестве лямбды.
@SafeVarargs
Функциональность varargs позволяет создавать методы с переменным количеством аргументов. До Java 5 единственной возможностью создания методов с необязательными параметрами было создание нескольких методов, каждый из которых с разным количеством параметров. Varargs позволяет создать один метод с переменным количеством параметров с помощью следующего синтаксиса:
// можно написать так: void printStrings(String. stringList) // вместо этого мы делаем: void printStrings(String string1, String string2)
Однако при использовании в аргументах метода обобщенных типов выдаются предупреждения. Аннотация @SafeVarargs позволяет подавить их:
package com.reflectoring; import java.util.Arrays; import java.util.List; public class SafeVarargsTest < private void printString(String test1, String test2) < System.out.println(test1); System.out.println(test2); >private void printStringVarargs(String. tests) < for (String test : tests) < System.out.println(test); >> private void printStringSafeVarargs(List. testStringLists) < for (ListtestStringList : testStringLists) < for (String testString : testStringList) < System.out.println(testString); >> > public static void main(String[] args) < SafeVarargsTest test = new SafeVarargsTest(); test.printString("String1", "String2"); test.printString("*******"); test.printStringVarargs("String1", "String2"); test.printString("*******"); ListtestStringList1 = Arrays.asList("One", "Two"); List testStringList2 = Arrays.asList("Three", "Four"); test.printStringSafeVarargs(testStringList1, testStringList2); > >
Методы printString() и printStringVarargs() приводят к одинаковому результату. Но при компиляции для метода printStringSafeVarargs() выдается предупреждение, поскольку в нем используются обобщенные типы:
javac -Xlint:unchecked ./com/reflectoring/SafeVarargsTest.java ./com/reflectoring/SafeVarargsTest.java:28: warning: [unchecked] Possible heap pollution from parameterized vararg type List private void printStringSafeVarargs(List. testStringLists) < ^ ./com/reflectoring/SafeVarargsTest.java:52: warning: [unchecked] unchecked generic array creation for varargs parameter of type List[] test.printStringSafeVarargs(testStringList1, testStringList2); ^ 2 warnings
Добавив аннотацию @SafeVarargs , мы можем избавиться от этого предупреждения:
@SafeVarargs private void printStringSafeVarargs(List. testStringLists)
Пользовательские аннотации
Мы можем создавать свои аннотации, например, для реализации следующей функциональности:
- Уменьшение дублирования кода.
- Автоматизация генерации бойлерплейт кода.
- Отлов ошибок во время компиляции, например, потенциальные Null Pointer Exception.
- Настройка поведения в рантайме на основе наличия аннотации.
Для примера рассмотрим аннотацию @Company :
@Company < name="ABC" city="XYZ" >public class CustomAnnotatedEmployee
При создании экземпляров класса CustomAnnotatedEmployee все экземпляры будут содержать одно и то же название компании (name) и города (city) — больше не нужно добавлять эту информацию в конструктор.
Создать пользовательскую аннотацию можно с помощью ключевого слова @interface :
public @interface Company
Чтобы указать информацию об области действия аннотации и о типах элементов, к которым она может быть применена, используются мета-аннотации.
Например, чтобы указать, что аннотация применяется только к классам, используется аннотация @Target(ElementType.TYPE) . А мета-аннотация @Retention(RetentionPolicy.RUNTIME) указывает, что аннотация должна быть доступна в рантайме.
С мета-аннотациями наша аннотация @Company выглядит следующим образом:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Company
Далее добавим атрибуты в нашу аннотацию: имя ( name ) и город ( city ). Добавляем их, как показано ниже:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Company
Создадим класс CustomAnnotatedEmployee и применим к нему аннотацию @Company :
@Company public class CustomAnnotatedEmployee < private int id; private String name; public CustomAnnotatedEmployee(int id, String name) < this.id = id; this.name = name; >public void getEmployeeDetails() < System.out.println("Employee Id: " + id); System.out.println("Employee Name: " + name); >>
Прочитать аннотацию @Company в рантайме можно следующим образом:
import java.lang.annotation.Annotation; public class TestCustomAnnotatedEmployee < public static void main(String[] args) < CustomAnnotatedEmployee employee = new CustomAnnotatedEmployee(1, "John Doe"); employee.getEmployeeDetails(); Annotation companyAnnotation = employee .getClass() .getAnnotation(Company.class); Company company = (Company)companyAnnotation; System.out.println("Company Name: " + company.name()); System.out.println("Company City: " + company.city()); >>
Результат будет следующий:
Employee Id: 1 Employee Name: John Doe Company Name: ABC Company City: XYZ
Анализируя аннотацию в рантайме, мы можем получить доступ к некоторой общей информации обо всех сотрудниках и избежать дублирования кода.
Мета-аннотации
Мета-аннотации — это аннотации, применяемые к другим аннотациям для предоставления информации об аннотации компилятору или среде выполнения.
Мета-аннотации могут ответить на следующие вопросы об аннотации:
- Может ли аннотация наследоваться дочерними классами?
- Должна ли аннотация отображаться в документации?
- Можно ли применить аннотацию несколько раз к одному и тому же элементу?
- К какому типу элементов можно применить аннотацию: к классу, методу, полю и т.д.?
- Обрабатывается ли аннотация во время компиляции или в рантайме?
@Inherited
По умолчанию аннотация не наследуется от родительского класса к дочернему. Мета-аннотация @Inherited позволяет ей наследоваться:
@Inherited @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Company < String name() default "ABC"; String city() default "XYZ"; >@Company public class CustomAnnotatedEmployee < private int id; private String name; public CustomAnnotatedEmployee(int id, String name) < this.id = id; this.name = name; >public void getEmployeeDetails() < System.out.println("Employee Id: " + id); System.out.println("Employee Name: " + name); >> public class CustomAnnotatedManager extends CustomAnnotatedEmployee < public CustomAnnotatedManager(int id, String name) < super(id, name); >>
Поскольку CustomAnnotatedEmployee аннотирован @Company , а CustomAnnotatedManager наследуется от него, то нет необходимости ставить аннотацию на класс CustomAnnotatedManager .
Давайте проверим это.
public class TestCustomAnnotatedManager < public static void main(String[] args) < CustomAnnotatedManager manager = new CustomAnnotatedManager(1, "John Doe"); manager.getEmployeeDetails(); Annotation companyAnnotation = manager .getClass() .getAnnotation(Company.class); Company company = (Company)companyAnnotation; System.out.println("Company Name: " + company.name()); System.out.println("Company City: " + company.city()); >>
Аннотация @Company доступна, хотя мы не указывали ее явно для класса Manager .
@Documented
@Documented указывает, что аннотация должна присутствовать в JavaDoc.
По умолчанию информация об аннотациях не отображается в JavaDoc-документации, но если использовать @Documented, она появится:
@Inherited @Documented @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Company
@Repeatable
@Repeatable позволяет использовать аннотацию несколько раз на одном методе, классе или поле. Для использования @Repeatable — аннотации необходимо создать аннотацию-контейнер, которая хранит значение в виде массива исходных аннотаций:>
@Target(ElementType.TYPE) @Repeatable(RepeatableCompanies.class) @Retention(RetentionPolicy.RUNTIME) public @interface RepeatableCompany
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface RepeatableCompanies < RepeatableCompany[] value() default<>; >
Использовать аннотацию можно следующим образом:
@RepeatableCompany @RepeatableCompany(name = "Name_2", city = "City_2") public class RepeatedAnnotatedEmployee
public class TestRepeatedAnnotation < public static void main(String[] args) < RepeatableCompany[] repeatableCompanies = RepeatedAnnotatedEmployee.class .getAnnotationsByType(RepeatableCompany.class); for (RepeatableCompany repeatableCompany : repeatableCompanies) < System.out.println("Name: " + repeatableCompany.name()); System.out.println("City: " + repeatableCompany.city()); >> >
Получим следующий результат, отображающий значение нескольких аннотаций @RepeatableCompany :
Name: Name_1 City: City_1 Name: Name_2 City: City_2
@Target
@Target определяет типы элементов, к которым может применяться аннотация. Например, в приведенном выше примере аннотация @Company была определена как TYPE, и поэтому может быть применена только к классам.
Давайте попробуем применить аннотацию @Company к методу:
@Company public class Employee < @Company public void getEmployeeStatus()< System.out.println("This is the Base Employee class"); >>
В этом случае мы получим ошибку компилятора: @Company not applicable to method .
Существуют следующие типы целей, названия которых говорят сами за себя:
- ElementType.ANNOTATION_TYPE
- ElementType.CONSTRUCTOR
- ElementType.FIELD
- ElementType.LOCAL_VARIABLE
- ElementType.METHOD
- ElementType.PACKAGE
- ElementType.PARAMETER
- ElementType.TYPE
@Retention
@Retention указывает, когда аннотация будет доступна:
- SOURCE — аннотация доступна в исходном коде и удаляется после компиляции.
- CLASS — аннотация сохраняется в class-файле во время компиляции, но недоступна при выполнении программы.
- RUNTIME — аннотация доступна в рантайме.
Если аннотация нужна только для проверки ошибок во время компиляции, как это делает @Override , мы используем SOURCE. Если аннотация нужна для обеспечения функциональности в рантайме, например, @Test в JUnit, то используем RUNTIME. Давайте поэкспериментируем с разными значениями RetentionPolicy :
@Target(ElementType.TYPE) @Retention(RetentionPolicy.CLASS) public @interface ClassRetention < >@Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface SourceRetention < >@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface RuntimeRetention
Создадим класс, который использует все три аннотации:
@SourceRetention @RuntimeRetention @ClassRetention public class EmployeeRetentionAnnotation
Для проверки доступности аннотаций запустите следующий код:
public class RetentionTest < public static void main(String[] args) < SourceRetention[] sourceRetention = new EmployeeRetentionAnnotation() .getClass() .getAnnotationsByType(SourceRetention.class); System.out.println("Source Retentions at runtime: " + sourceRetention.length); RuntimeRetention[] runtimeRetention = new EmployeeRetentionAnnotation() .getClass() .getAnnotationsByType(RuntimeRetention.class); System.out.println("Runtime Retentions at runtime: " + runtimeRetention.length); ClassRetention[] classRetention = new EmployeeRetentionAnnotation() .getClass() .getAnnotationsByType(ClassRetention.class); System.out.println("Class Retentions at runtime: " + classRetention.length); >>
Результат будет следующим:
Source Retentions at runtime: 0 Runtime Retentions at runtime: 1 Class Retentions at runtime: 0
Итак, мы убедились, что в рантайме доступна только RUNTIME-аннотация.
Классификация аннотаций
Аннотации можно классифицировать по количеству передаваемых в них параметров: без параметров, с одним параметром и с несколькими параметрами.
Маркерные аннотации
Маркерные аннотации не содержат никаких членов или данных. Для определения наличия аннотации можно использовать метод isAnnotationPresent() .
Например, если бы у нашей компании было несколько клиентов с разными способами передачи данных, мы могли бы аннотировать класс аннотацией, указывающей способ передачи данных:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface CSV
Класс Client может использовать аннотацию следующим образом:
@CSV public class XYZClient
Обработать аннотацию можно следующим образом:
public class TestMarkerAnnotation < public static void main(String[] args) < XYZClient client = new XYZClient(); Class clientClass = client.getClass(); if (clientClass.isAnnotationPresent(CSV.class))< System.out.println("Write client data to CSV."); >else < System.out.println("Write client data to Excel file."); >> >
На основании присутствия аннотации @CSV , мы можем решить, куда записать информацию — в CSV или в файл Excel. Приведенная выше программа выдаст следующий результат:
Write client data to CSV.
Аннотации с одним значением
Аннотации с одним значением содержат только один атрибут, который принято называть value.
Давайте создадим аннотацию SingleValueAnnotationCompany с одним атрибутом value :
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface SingleValueAnnotationCompany
Создайте класс, использующий аннотацию:
@SingleValueAnnotationCompany("XYZ") public class SingleValueAnnotatedEmployee < private int id; private String name; public SingleValueAnnotatedEmployee(int id, String name) < this.id = id; this.name = name; >public void getEmployeeDetails() < System.out.println("Employee Id: " + id); System.out.println("Employee Name: " + name); >>
Запустите следующий пример:
public class TestSingleValueAnnotatedEmployee < public static void main(String[] args) < SingleValueAnnotatedEmployee employee = new SingleValueAnnotatedEmployee(1, "John Doe"); employee.getEmployeeDetails(); Annotation companyAnnotation = employee .getClass() .getAnnotation(SingleValueAnnotationCompany.class); SingleValueAnnotationCompany company = (SingleValueAnnotationCompany)companyAnnotation; System.out.println("Company Name: " + company.value()); >>
Переданное значение "XYZ" переопределяет значение атрибута аннотации по умолчанию. Результат выглядит следующим образом:
Employee Id: 1 Employee Name: John Doe Company Name: XYZ
Полные аннотации
Они состоят из нескольких пар "имя-значение". Например, Company(name = "ABC", city = "XYZ") . Рассмотрим наш исходный пример Company:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Company
Давайте создадим класс MultiValueAnnotatedEmployee со значением параметров, как показано ниже. Значения по умолчанию будут перезаписаны.
@Company(name = "AAA", city = "ZZZ") public class MultiValueAnnotatedEmployee
Запустите следующий пример:
public class TestMultiValueAnnotatedEmployee < public static void main(String[] args) < MultiValueAnnotatedEmployee employee = new MultiValueAnnotatedEmployee(); Annotation companyAnnotation = employee.getClass().getAnnotation(Company.class); Company company = (Company)companyAnnotation; System.out.println("Company Name: " + company.name()); System.out.println("Company City: " + company.city()); >>
Company Name: AAA Company City: ZZZ
Практический пример
В качестве практического примера обработки аннотаций напишем простой аналог аннотации @Test из JUnit. Пометив методы аннотацией @Test , мы сможем определить в рантайме, какие методы тестового класса нужно запускать как тесты.
Сначала создадим маркерную аннотацию для методов-тестов:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Test
Далее создадим класс AnnotatedMethods , в котором применим аннотацию @Test к методу test1() . Это позволит выполнить метод в рантайме. У метода test2() аннотации нет и он не должен выполняться.
public class AnnotatedMethods < @Test public void test1() < System.out.println("This is the first test"); >public void test2() < System.out.println("This is the second test"); >>
Теперь напишем код для запуска тестов из класса AnnotatedMethods :
import java.lang.annotation.Annotation; import java.lang.reflect.Method; public class TestAnnotatedMethods < public static void main(String[] args) throws Exception < ClassannotatedMethodsClass = AnnotatedMethods.class; for (Method method : annotatedMethodsClass.getDeclaredMethods()) < Annotation annotation = method.getAnnotation(Test.class); Test test = (Test) annotation; // If the annotation is not null if (test != null) < try < method.invoke(annotatedMethodsClass .getDeclaredConstructor() .newInstance()); >catch (Throwable ex) < System.out.println(ex.getCause()); >> > > >
Через метод getDeclaredMethods() мы получаем методы класса AnnotatedMethods . Затем перебираем методы и проверяем, аннотирован ли метод аннотацией @Test . Наконец, выполняем вызов методов, которые были аннотированы с помощью @Test .
В результате метод test1() выполнится, поскольку он аннотирован @Test , а test2() нет, так как он без аннотации @Test .
This is the first test
Заключение
Мы сделали обзор основных стандартных аннотаций и рассмотрели, как создавать и обрабатывать свои аннотации.
Возможностей по использованию аннотаций гораздо больше, чем мы рассмотрели. Например, можно автоматически генерировать код для паттерна Builder. Шаблон проектирования Builder (строитель) используется как альтернатива конструкторам, когда в конструкторы передается много параметров или есть необходимость в нескольких конструкторах с необязательными параметрами. При большом количестве таких классов возможность генерации кода обработчиком аннотаций сэкономит много времени и поможет избежать дублирования кода.
Примеры кода вы можете найти на GitHub.
Всех желающих приглашаем на Demo-занятие «Объектно-ориентированное и функциональное программирование». На вебинаре поговорим о стилях программирования и необходимости каждого из них. Разберём основные принципы объектно-ориентированного стиля (Инкапсуляция, Наследование, Полиморфизм), а также возможности функционального стиля, которые предоставляет язык Java. Регистрация для всех желающих по ссылке.
- java
- Аннотации в Java
- ООП
- функциональное программирование
- Блог компании OTUS
- Java
Аннотации. Как пользоваться
Как ты уже, наверное, знаешь – аннотации – это такие специальные слова, которые можно размещать рядом с классами, полями, методами и переменными.
— Ага. Очень часто их встречаю.
— Иногда их называют еще метаданными. Основная их задача – хранить некоторую дополнительную информацию о методах, полях и классах.
— А для кого они ее хранят?
— Это очень хороший вопрос.
Раз эти аннотации пишут, значит, они кому-то нужны.
Аннотации позволяют хранить дополнительную информацию о коде и элементах программы, но формально не являются частью кода.
Аннотации можно использовать для генерации XML, определения, устарел метод или нет, отслеживания ошибок и т.п.
Пример аннотаций в коде:
@CatInfo(manager=Catmanager.class, unique=true) class Cat < @Name("Murka") private String name; @SuppressWarnings(value = "unchecked") void getUniqueCatName() < >>
Как ты видишь, в аннотациях можно хранить данные.
Если аннотация имеет только одно поле value , то его можно опускать:
@SuppressWarnings("unchecked") void getUniqueCatName()
Если параметров в скобках нет, скобки тоже можно не писать:
@Override void getUniqueCatName()
Создать свою аннотацию очень легко. Объявление аннотации – практически идентично объявлению интерфейса.
@interface CatManager
Есть всего пара отличий.
Во-первых, перед словом interface ставится символ «@».
Во-вторых, аннотация может содержать значения по умолчанию. Для этого используется слово default. См. пример выше. Такие параметры являются необязательными и их можно опускать при добавлении аннотаций.
— Ага. Все оказалось проще, чем я думал. А то я уже шарахался от них, как Рободьявол от святой воды. Неприятно, когда в коде куча всяких штук, которые до конца не понимаешь.
— О, хорошо, что напомнил, хочу еще рассказать об аннотациях, используемых компилятором.
Таких аннотаций всего 3. Пока три.
@Deprecated.
Класс или метод можно пометить аннотацией @Deprecated. Тогда компилятор будет выдавать предупреждение (предупреждение — это не ошибка), а Intellij IDEA будет отображать этот метод как перечеркнутый. Примерно так:
Date date = new Date(); int year = date.getYear();
@Override.
При переопределении метода, хорошим тоном считается добавить ему аннотацию @Override.
— А для чего? Вроде же IDEA и так показывает, переопределен метод или нет?
— Во-первых, то IDEA, а то синтаксис Java.
А во-вторых, гипотетически может быть ситуация, когда метод базового класса переименуют, а метод наследника – нет. И программа будет работать неправильно, но никто этого не заметит. Для предотвращения таких ситуаций и была придумана эта аннотация:
@Override void getUniqueCatName()
@SuppressWarnings.
— Иногда компилятор выводит очень много предупреждений. Или мы знаем о «проблемах» и сознательно пошли на такое использование. С помощью этой аннотации можно скрыть часть из них.
С помощью аннотации @SuppressWarnings , программист может сказать компилятору: не нужно показывать предупреждения, так задумано, это не ошибка. Пример:
@SuppressWarnings("unchecked") void getUniqueCatName()
— Что-то я немного устал, пойду, промочу горло. Давай продолжим после перерыва, ок?

Комментарии (26)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
overbf bf Уровень 40
10 ноября 2023
Вернулся сюда, что бы оставить это: https://javarush.com/groups/posts/1896-java-annotacii-chto-ehto-i-kak-ehtim-poljhzovatjhsja а то дальше вообще ничего не понятно.
Ra Уровень 51 Student
28 июля 2023
Когда пишете аннотацию, нажимайте Ctrl+P. И вообще всегда, когда нужны параметры метода)
Anonymous #3091828 Уровень 51
1 декабря 2022
Чет комментов становится оч мало, где люди подевались.
Рогов Игорь Уровень 17
31 мая 2022
не раскрыта цель аннотаций и их прям такая необходимость
Valua Sinicyn Уровень 41
26 февраля 2021
Тема маркеров аннотаций не раскрыта. Маркеры @SuppressWarnings: • all - отключение всех предупреждений; • boxing - отключение предупреждений, связанных с приведением к классам и простым типам; • cast - отключение предупреждений, связанных с преобразованием типов; • dep-ann - отключение предупреждений, связанных с устаревшими аннотациями; • deprecation - отключение предупреждений, связанных с устареванием; • fallthrough - отключение предупреждений, связанных с отсутствующими точками прерывания в операторах выбора; • finally - отключение предупреждений, связанных с окончательными блокировками, не возвращающими управление; • hiding - отключение предупреждений, связанных с локальными объектами, скрывающими переменные; • incomplete-switch - отключение предупреждений, связанных с недостающими элементами в операторах выбора (enum case); • javadoc - отключение предупреждений, связанных с предупреждениями javadoc; • nls отключение предупреждений, связанных с литеральными строками, не являющимися nls; • null - отключение предупреждений, связанных с анализом null; • rawtypes - отключение предупреждений, связанных с использованием непараметризованных типов; • resource - отключение предупреждений, связанных с использованием ресурсов типа Closeable; • restriction - отключение предупреждений, связанных с использованием нерекомендованных или запрещенных ресурсов; • serial - отключение предупреждений, связанных с недостающим полем serialVersionUID в классе, допускающем сериализацию; • static-access - отключение предупреждений, связанных с некорректными операциями статического доступа; • static-method - отключение предупреждений, связанных с методами, которые могут быть определены с модификатором static; • super - отключение предупреждений, связанных с переопределением метода без вызова базового метода; • synthetic-access - отключение предупреждений, связанных с неоптимизированным доступом из внутренних классов; • sync-override - отключение предупреждений из
ram0973 Уровень 41
12 января 2021
Небольшой бесплатный курс по Спрингу. Курс простой, понятный и демонстрирует аннотации, а также REST, SQL, HTTP, JSON. Самое время пройти за несколько вечеров. Интересно, что в IDEA есть и генератор HTTP-запросов, и SQL-консоль.Также официальный туториал , сложнее
Pavlo Buidenkov Уровень 41
30 мая 2020
а на работе прежде чем добавлять свою супер крутую аннотацию, нужно иметь хороший разговор с коллегами и аргументировать им почему она крайне необходима, и только после того как они согласны уже её реализовывать. ни для кого не секрет, что многие аннотации в коде просто раздражают и, иногда, уменьшают читабельность и предсказуемость кода.