Поиск…


Вступление

В Java аннотация - это форма синтаксических метаданных, которые могут быть добавлены в исходный код Java. Он предоставляет данные о программе, которая не является частью самой программы. Аннотации не оказывают прямого влияния на работу кода, который они комментируют. Классы, методы, переменные, параметры и пакеты могут быть аннотированы.

Синтаксис

  • @AnnotationName // «Аннотирование маркера» (без параметров)
  • @AnnotationName (someValue) // устанавливает параметр с именем 'value'
  • @AnnotationName (param1 = value1) // named parameter
  • @AnnotationName (param1 = value1, param2 = value2) // несколько именованных параметров
  • @AnnotationName (param1 = {1, 2, 3}) // параметр имени array
  • @AnnotationName ({value1}) // массив с одним элементом в качестве параметра с именем 'value'

замечания

Типы параметров

Для параметров могут использоваться только постоянные выражения следующих типов, а также массивы этих типов:

  • String
  • Class
  • примитивные типы
  • Типы перечислений
  • Типы аннотаций

Встроенные аннотации

Стандартная версия Java содержит предопределенные аннотации. Вам не нужно определять их самостоятельно, и вы можете использовать их немедленно. Они позволяют компилятору разрешить некоторую фундаментальную проверку методов, классов и кода.

@Override

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

Бетонный суперкласс

public class Vehicle {
   public void drive() {
        System.out.println("I am driving");
   }
}

class Car extends Vehicle {
    // Fine
    @Override
    public void drive() {
        System.out.prinln("Brrrm, brrm");
    }
}

Абстрактный класс

abstract class Animal  {
   public abstract void makeNoise(); 
}

class Dog extends Animal {
    // Fine
    @Override
    public void makeNoise() {
        System.out.prinln("Woof");
    }
}

Не работает

class Logger1 {
    public void log(String logString) {
        System.out.prinln(logString);
    }
}

class Logger2 {
    // This will throw compile-time error. Logger2 is not a subclass of Logger1. 
    // log method is not overriding anything
    @Override
    public void log(String logString) {
        System.out.println("Log 2" + logString);
    }
}

Основная цель - уловить туманность, где вы думаете, что вы переопределяете метод, но на самом деле определяете новый.

class Vehicle {
   public void drive() {
        System.out.println("I am driving");
   }
}

class Car extends Vehicle {
    // Compiler error. "dirve" is not the correct method name to override.
    @Override
    public void dirve() {
        System.out.prinln("Brrrm, brrm");
    }
}

Обратите внимание, что значение @Override со временем изменилось:

  • В Java 5 это означало, что аннотированный метод должен был переопределить не абстрактный метод, объявленный в цепочке суперкласса.
  • Начиная с Java 6, он также выполняется, если аннотированный метод реализует абстрактный метод, объявленный в иерархии классов суперклассов / интерфейсов.

(Иногда это может вызвать проблемы при обратном переносе кода на Java 5.)

@Deprecated

Это означает, что метод устарел. Это может быть несколько причин:

  • API является ошибочным и нецелесообразно исправлять,

  • использование API, вероятно, приведет к ошибкам,

  • API был заменен другим API,

  • API устарел,

  • API является экспериментальным и подлежит несовместимым изменениям,

  • или любую комбинацию вышеуказанного.

Конкретную причину устаревания обычно можно найти в документации API.


Аннотации заставят компилятор испускать ошибку, если вы ее используете. IDE также могут выделить этот метод как-то как устаревший

class ComplexAlgorithm {
    @Deprecated
    public void oldSlowUnthreadSafeMethod() {
        // stuff here
    }
    
    public void quickThreadSafeMethod() {
        // client code should use this instead
    }
}

@SuppressWarnings

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

Эта аннотация может применяться ко всему классу, методу или строке. В качестве параметра используется категория предупреждения.

@SuppressWarnings("deprecation")
public class RiddledWithWarnings {
    // several methods calling deprecated code here
}

@SuppressWarning("finally")
public boolean checkData() {
    // method calling return from within finally block
}

Лучше максимально ограничить объем аннотации, чтобы предотвратить непредвиденные предупреждения. Например, ограничение объема аннотации на одну строку:

ComplexAlgorithm algorithm = new ComplexAlgorithm();
@SuppressWarnings("deprecation") algoritm.slowUnthreadSafeMethod(); 
// we marked this method deprecated in an example above

@SuppressWarnings("unsafe") List<Integer> list = getUntypeSafeList(); 
// old library returns, non-generic List containing only integers

Предупреждения, поддерживаемые этой аннотацией, могут отличаться от компилятора к компилятору. Только unchecked и deprecation предупреждения упомянуты в JLS. Непризнанные типы предупреждений будут игнорироваться.

@SafeVarargs

Из-за стирания типа void method(T... t) будет преобразован в void method(Object[] t) что означает, что компилятор не всегда может проверить, что использование varargs является безопасным по типу. Например:

private static <T> void generatesVarargsWarning(T... lists) {

Существуют случаи, когда использование безопасно, и в этом случае вы можете аннотировать метод с SafeVarargs аннотации SafeVarargs для подавления предупреждения. Это явно скрывает предупреждение, если ваше использование также небезопасно.

@FunctionalInterface

Это необязательная аннотация, используемая для обозначения FunctionalInterface. Это заставит компилятор жаловаться, если он не соответствует спецификации FunctionalInterface (имеет один абстрактный метод)

@FunctionalInterface
public interface ITrade {
  public boolean check(Trade t);
}

@FunctionalInterface
public interface Predicate<T> {
  boolean test(T t);
}

Проверка аннотации выполнения через отражение

API Reflection Java позволяет программисту выполнять различные проверки и операции над полями, методами и аннотациями классов во время выполнения. Однако для того, чтобы аннотация была видимой во время выполнения, RetentionPolicy необходимо изменить на RUNTIME , как показано в следующем примере:

@interface MyDefaultAnnotation {

}

@Retention(RetentionPolicy.RUNTIME)
@interface MyRuntimeVisibleAnnotation {

}

public class AnnotationAtRuntimeTest {

    @MyDefaultAnnotation
    static class RuntimeCheck1 {
    }
    
    @MyRuntimeVisibleAnnotation
    static class RuntimeCheck2 {
    }
    
    public static void main(String[] args) {
        Annotation[] annotationsByType = RuntimeCheck1.class.getAnnotations();
        Annotation[] annotationsByType2 = RuntimeCheck2.class.getAnnotations();

        System.out.println("default retention: " + Arrays.toString(annotationsByType));
        System.out.println("runtime retention: " + Arrays.toString(annotationsByType2));
    }
}

Определение типов аннотаций

Типы аннотаций определяются с помощью @interface . Параметры определяются аналогично методам регулярного интерфейса.

@interface MyAnnotation {
    String param1();
    boolean param2();
    int[] param3();  // array parameter 
}

Значения по умолчанию

@interface MyAnnotation {
    String param1() default "someValue";
    boolean param2() default true;
    int[] param3() default {};
}

Мета-аннотаций

Мета-аннотации - это аннотации, которые могут применяться к типам аннотаций. Специальная предопределенная мета-аннотация определяет, как можно использовать типы аннотаций.

@Target

Мета-аннотация @Target ограничивает типы, к которым может применяться аннотация.

@Target(ElementType.METHOD)
@interface MyAnnotation {
    // this annotation can only be applied to methods
}

Несколько значений могут быть добавлены с использованием нотации массива, например @Target({ElementType.FIELD, ElementType.TYPE})

Доступные значения

ElementType цель пример использования целевого элемента
ANNOTATION_TYPE типы аннотаций
@Retention(RetentionPolicy.RUNTIME) 
@interface MyAnnotation
КОНСТРУКТОР конструкторы
@MyAnnotation
public MyClass() {}
Область поля, константы перечисления
@XmlAttribute
private int count;
LOCAL_VARIABLE объявления переменных внутри методов
for (@LoopVariable int i = 0; i < 100; i++) {
@Unused
String resultVariable;
}
ПАКЕТ пакет (в package-info.java )
@Deprecated
package very.old;
МЕТОД методы
@XmlElement
public int getCount() {...}
ПАРАМЕТР параметры метода / конструктора
public Rectangle(
@NamedArg("width") double width,
@NamedArg("height") double height) {
...
}
ТИП классы, интерфейсы, перечисления
@XmlRootElement
public class Report {}
Java SE 8
ElementType цель пример использования целевого элемента
TYPE_PARAMETER Объявление параметров типа
public <@MyAnnotation T> void f(T t) {}
TYPE_USE Использование типа
Object o = "42";
String s = (@MyAnnotation String) o;

@Retention

Мета-аннотация @Retention определяет видимость аннотации во время процесса или выполнения компиляции приложений. По умолчанию аннотации включены в .class файлы, но не отображаются во время выполнения. Чтобы сделать аннотацию доступной во время выполнения, в этой аннотации необходимо установить RetentionPolicy.RUNTIME .

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
    // this annotation can be accessed with reflections at runtime
}

Доступные значения

Политика удержания эффект
УЧЕБНЫЙ КЛАСС Аннотации доступны в файле .class , но не во время выполнения
RUNTIME Аннотации доступны во время выполнения и могут быть доступны посредством отражения
ИСТОЧНИК Аннотации доступны во время компиляции, но не добавляются в .class . Аннотацию можно использовать, например, обработчиком аннотации.

@Documented

Мета-аннотация @Documented используется для обозначения аннотаций, использование которых должно быть документировано генераторами документации API, такими как javadoc . Он не имеет значений. С помощью @Documented все классы, использующие аннотацию, будут перечислены на их сгенерированной странице документации. Без @Documented невозможно увидеть, какие классы используют аннотацию в документации.

@Inherited

@Inherited метаинформация @Inherited имеет отношение к аннотациям, которые применяются к классам. Он не имеет значений. Пометка аннотации как @Inherited изменяет способ обработки аннотаций.

  • Для не унаследованной аннотации запрос рассматривает только исследуемый класс.
  • Для унаследованной аннотации запрос также проверяет цепочку суперкласса (рекурсивно) до тех пор, пока не будет найден экземпляр аннотации.

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

@Repeatable

@Repeatable мета-аннотация @Repeatable в Java 8. Она указывает, что к @Repeatable аннотации можно добавить несколько экземпляров аннотации. Эта мета-аннотация не имеет значений.

Получение значений аннотации во время выполнения

Вы можете получить текущие свойства аннотации, используя Reflection, чтобы получить метод или поле или класс, к которым применена аннотация, и затем выбор желаемых свойств.

@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
    String key() default "foo";
    String value() default "bar";
}


class AnnotationExample {
    // Put the Annotation on the method, but leave the defaults
    @MyAnnotation
    public void testDefaults() throws Exception {
        // Using reflection, get the public method "testDefaults", which is this method with no args
        Method method = AnnotationExample.class.getMethod("testDefaults", null);

        // Fetch the Annotation that is of type MyAnnotation from the Method
        MyAnnotation annotation = (MyAnnotation)method.getAnnotation(MyAnnotation.class);

        // Print out the settings of the Annotation
        print(annotation);
    }

    //Put the Annotation on the method, but override the settings
    @MyAnnotation(key="baz", value="buzz")
    public void testValues() throws Exception {
        // Using reflection, get the public method "testValues", which is this method with no args
        Method method = AnnotationExample.class.getMethod("testValues", null);

        // Fetch the Annotation that is of type MyAnnotation from the Method
        MyAnnotation annotation = (MyAnnotation)method.getAnnotation(MyAnnotation.class);

        // Print out the settings of the Annotation
        print(annotation);
    }

    public void print(MyAnnotation annotation) {
        // Fetch the MyAnnotation 'key' & 'value' properties, and print them out 
        System.out.println(annotation.key() + " = " + annotation.value());
    }

    public static void main(String[] args) {
        AnnotationExample example = new AnnotationExample();
        try {
            example.testDefaults();
            example.testValues();
        } catch( Exception e ) {
            // Shouldn't throw any Exceptions
            System.err.println("Exception [" + e.getClass().getName() + "] - " + e.getMessage());
            e.printStackTrace(System.err);
        }
    }
}

Выход будет

foo = bar
baz = buzz

Повторяющиеся аннотации

До Java 8 два экземпляра одной аннотации не могли быть применены к одному элементу. Стандартное обходное решение заключалось в использовании аннотации контейнера, содержащей массив некоторой другой аннотации:

// Author.java
@Retention(RetentionPolicy.RUNTIME)
public @interface Author {
    String value();
}

// Authors.java
@Retention(RetentionPolicy.RUNTIME)
public @interface Authors {
    Author[] value();
}

// Test.java
@Authors({
    @Author("Mary"),
    @Author("Sam")
})
public class Test {
    public static void main(String[] args) {
        Author[] authors = Test.class.getAnnotation(Authors.class).value();
        for (Author author : authors) {
            System.out.println(author.value());
            // Output:
            // Mary
            // Sam
        }
    }
}
Java SE 8

Java 8 обеспечивает более чистый, более прозрачный способ использования аннотаций контейнеров, используя аннотацию @Repeatable . Сначала добавим это в класс Author :

@Repeatable(Authors.class)

Это говорит Java обрабатывать несколько аннотаций @Author как если бы они были окружены контейнером @Authors . Мы также можем использовать Class.getAnnotationsByType() для доступа к массиву @Author своим собственным классом, а не через его контейнер:

@Author("Mary")
@Author("Sam")
public class Test {
    public static void main(String[] args) {
        Author[] authors = Test.class.getAnnotationsByType(Author.class);
        for (Author author : authors) {
            System.out.println(author.value());
            // Output:
            // Mary
            // Sam
        }
    }
}

Унаследованные аннотации

По умолчанию аннотации классов не применяются к типам, расширяющим их. Это можно изменить, добавив аннотацию @Inherited в определение аннотации

пример

Рассмотрим следующие 2 аннотации:

@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface InheritedAnnotationType {
}

а также

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface UninheritedAnnotationType {
}

Если три класса аннотируются следующим образом:

@UninheritedAnnotationType
class A {
}

@InheritedAnnotationType
class B extends A {
}

class C extends B {
}

запуск этого кода

System.out.println(new A().getClass().getAnnotation(InheritedAnnotationType.class));
System.out.println(new B().getClass().getAnnotation(InheritedAnnotationType.class));
System.out.println(new C().getClass().getAnnotation(InheritedAnnotationType.class));
System.out.println("_________________________________");
System.out.println(new A().getClass().getAnnotation(UninheritedAnnotationType.class));
System.out.println(new B().getClass().getAnnotation(UninheritedAnnotationType.class));
System.out.println(new C().getClass().getAnnotation(UninheritedAnnotationType.class));

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

null
@InheritedAnnotationType()
@InheritedAnnotationType()
_________________________________
@UninheritedAnnotationType()
null
null

Обратите внимание, что аннотации могут наследоваться только от классов, а не от интерфейсов.

Обработка времени компиляции с использованием обработчика аннотаций

В этом примере показано, как выполнить проверку времени компиляции аннотированного элемента.

Аннотации

@Setter - это маркер, который можно применить к методам. Аннотации будут отброшены во время компиляции, которые впоследствии не будут доступны.

package annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.METHOD)
public @interface Setter {
}

Обработчик аннотации

Класс SetterProcessor используется компилятором для обработки аннотаций. Он проверяет, если методы аннотированные с @Setter аннотаций являются public , неправительственные static методы с именем , начинающимся с set и имеющий заглавную букву как 4 буквы. Если одно из этих условий не выполняется, в Messager записывается ошибка. Компилятор записывает это в stderr, но другие инструменты могут использовать эту информацию по-разному. Например, IDE NetBeans позволяет пользователю задавать обработчики аннотаций, которые используются для отображения сообщений об ошибках в редакторе.

package annotation.processor;

import annotation.Setter;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;

@SupportedAnnotationTypes({"annotation.Setter"})
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class SetterProcessor extends AbstractProcessor {

    private Messager messager;

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        // get elements annotated with the @Setter annotation
        Set<? extends Element> annotatedElements = roundEnv.getElementsAnnotatedWith(Setter.class);

        for (Element element : annotatedElements) {
            if (element.getKind() == ElementKind.METHOD) {
                // only handle methods as targets
                checkMethod((ExecutableElement) element);
            }
        }

        // don't claim annotations to allow other processors to process them
        return false;
    }

    private void checkMethod(ExecutableElement method) {
        // check for valid name
        String name = method.getSimpleName().toString();
        if (!name.startsWith("set")) {
            printError(method, "setter name must start with \"set\"");
        } else if (name.length() == 3) {
            printError(method, "the method name must contain more than just \"set\"");
        } else if (Character.isLowerCase(name.charAt(3))) {
            if (method.getParameters().size() != 1) {
                printError(method, "character following \"set\" must be upper case");
            }
        }

        // check, if setter is public
        if (!method.getModifiers().contains(Modifier.PUBLIC)) {
            printError(method, "setter must be public");
        }

        // check, if method is static
        if (method.getModifiers().contains(Modifier.STATIC)) {
            printError(method, "setter must not be static");
        }
    }

    private void printError(Element element, String message) {
        messager.printMessage(Diagnostic.Kind.ERROR, message, element);
    }

    @Override
    public void init(ProcessingEnvironment processingEnvironment) {
        super.init(processingEnvironment);

        // get messager for printing errors
        messager = processingEnvironment.getMessager();
    }

}

упаковка

Для применения компилятором процессор обработки аннотаций должен быть доступен для SPI (см. ServiceLoader ).

Для этого нужно добавить текстовый файл META-INF/services/javax.annotation.processing.Processor необходимо добавить в файл jar, содержащий процессор аннотации, и аннотацию в дополнение к другим файлам. В файле должно быть указано полное имя обработчика аннотаций, то есть оно должно выглядеть так:

annotation.processor.SetterProcessor

Мы предположим, что файл jar называется AnnotationProcessor.jar ниже.

Пример аннотированного класса

Следующий класс является примером класса в пакете по умолчанию с аннотациями, которые применяются к правильным элементам в соответствии с политикой хранения. Однако только обработчик аннотации рассматривает второй метод как действительную цель аннотации.

import annotation.Setter;

public class AnnotationProcessorTest {
    
    @Setter
    private void setValue(String value) {}

    @Setter
    public void setString(String value) {}
    
    @Setter
    public static void main(String[] args) {}
    
}

Использование обработчика аннотации с javac

Если обработчик аннотации обнаружен с использованием SPI, он автоматически используется для обработки аннотированных элементов. Например, компиляция класса AnnotationProcessorTest с использованием

javac -cp AnnotationProcessor.jar AnnotationProcessorTest.java

дает следующий результат

AnnotationProcessorTest.java:6: error: setter must be public
    private void setValue(String value) {}
                 ^
AnnotationProcessorTest.java:12: error: setter name must start with "set"
    public static void main(String[] args) {}
                       ^
2 errors

вместо компиляции в обычном режиме. Файл .class не создается.

Этого можно предотвратить, указав параметр -proc:none для javac . Вы также можете отказаться от обычной компиляции, указав -proc:only вместо этого.

Интеграция IDE

Netbeans

Обработчики аннотаций могут использоваться в редакторе NetBeans. Для этого в настройках проекта необходимо указать процессор аннотации:

  1. перейдите в « Project Properties > « Build > « Compiling

  2. добавить флажки для Enable Annotation Processing и Enable Annotation Processing in Editor

  3. нажмите « Add рядом с списком процессоров аннотаций

  4. в появившемся всплывающем окне введите полное имя класса обработчика аннотации и нажмите « Ok .

Результат

Окно редактора с настраиваемым сообщением об ошибке

Идея аннотаций

Спецификация языка Java описывает аннотации следующим образом:

Аннотирование - это маркер, который связывает информацию с конструкцией программы, но не влияет на время выполнения.

Аннотации могут отображаться перед типами или объявлениями. Они могут появляться в месте, где они могут применяться как к типу, так и к объявлению.
То, к чему относится аннотация, регулируется «мета-аннотацией» @Target . Дополнительную информацию см. В разделе «Определение типов аннотаций» .

Аннотации используются для множества целей. Структуры, такие как Spring и Spring-MVC, используют аннотации для определения того, где должны быть введены зависимости или где должны быть маршрутизированы запросы.

Другие фреймворки используют аннотации для генерации кода. Ломбок и JPA - яркие примеры, которые используют аннотации для генерации кода Java (и SQL).

Цель этой темы - предоставить полный обзор:

  • Как определить свои собственные аннотации?

  • Какие аннотации предоставляет Java-язык?

  • Как используются аннотации на практике?

Аннотации для параметров «этого» и приемника

Когда впервые были введены аннотации Java, не было никаких условий для аннотирования цели метода экземпляра или параметра скрытого конструктора для конструктора внутренних классов. Это было исправлено на Java 8 с добавлением объявлений параметров приемника ; см. JLS 8.4.1 .

Параметр получателя является необязательным синтаксическим устройством для метода экземпляра или конструктора внутреннего класса. Для метода экземпляра параметр приемника представляет объект, для которого вызывается метод. Для конструктора внутреннего класса параметр-приемник представляет собой немедленно включающий экземпляр вновь созданного объекта. В любом случае параметр приемника существует только для того, чтобы разрешить тип отображаемого объекта в исходном коде, чтобы тип мог быть аннотирован. Параметр приемника не является формальным параметром; точнее, это не объявление какой-либо переменной (§4.12.3), оно никогда не связано ни с каким значением, переданным в качестве аргумента в выражении вызова метода или в выражении для создания экземпляра класса, и оно не оказывает никакого влияния на время выполнения.

Следующий пример иллюстрирует синтаксис для обоих типов параметров приемника:

public class Outer {
    public class Inner {
        public Inner (Outer this) {
           // ...
        }
        public void doIt(Inner this) {
           // ...
        }
    }
}

Единственная цель параметров приемника - дать вам возможность добавлять аннотации. Например, у вас может быть пользовательская аннотация @IsOpen , целью которой является утверждение, что объект Closeable не был закрыт при вызове метода. Например:

public class MyResource extends Closeable {
    public void update(@IsOpen MyResource this, int value) {
        // ...
    }

    public void close() {
        // ...
    }
}

На одном уровне аннотация @IsOpen на this может просто служить документацией. Однако мы могли бы сделать больше. Например:

  • Обработчик аннотации может вставить проверку времени выполнения, что this не в закрытом состоянии при вызове update .
  • Средство проверки кода может выполнять статический анализ кода, чтобы найти случаи, когда this может быть закрыто при вызове update .

Добавить несколько значений аннотации

Параметр Annotation может принимать несколько значений, если он определен как массив. Например, стандартная аннотация @SuppressWarnings определяется следующим образом:

public @interface SuppressWarnings {
    String[] value();
}

Параметр value представляет собой массив строк. Вы можете установить несколько значений, используя нотацию, похожую на инициализаторы массива:

@SuppressWarnings({"unused"})
@SuppressWarnings({"unused", "javadoc"})

Если вам нужно только установить одно значение, скобки можно опустить:

@SuppressWarnings("unused") 


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow