English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Основной учебник Java

Java Управление потоком

Java Массив

Java Ориентированность на объекты (I)

Java Ориентированность на объекты (II)

Java Ориентированность на объекты (III)

Обработка исключений Java

Java Список (List)

Java Queue (очередь)

Java Map коллекции

Java Set коллекции

Java Вход/Выход (I/O)

Java Reader/Writer

Другие темы Java

Типы анализаторов Java

В этом уроке мы будем изучать различные типы Java анализаторов с помощью примеров.

Java анализаторы — это метаданные нашего исходного кода (данные о данных). Java SE предоставляет несколько предопределенных анализаторов. Кроме того, мы можем создавать пользовательские анализаторы по мере необходимости.

Если вы не знаете, что такое анализаторы, пожалуйста, посетитеJava аннотацииУрок.

Эти анализаторы можно классифицировать как:

1. Предопределенные анализаторы

  • @Deprecated

  • @Override

  • @SuppressWarnings

  • @SafeVarargs

  • @FunctionalInterface

2. Пользовательские аннотации

3. Мета-аннотации

  • @Retention

  • @Documented

  • @Target

  • @Inherited

  • @Repeatable

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

1. @Deprecated

@Deprecated анализатор — это маркер анализатора, указывающий на элементы (классы, методы, поля и т.д.), которые устарели и были заменены обновленными элементами.

ее грамматика такова:

@Deprecated
accessModifier returnType deprecatedMethodName() { ... }

Когда программа использует элементы, объявленные как弃нутые, компилятор генерирует предупреждение.

Мы используем метку @deprecated в Javadoc для записи элементов, которые были弃нуты.

/**
 * @deprecated
 * Почему он был弃нут
 */
@Deprecated
accessModifier returnType deprecatedMethodName() { ... }

Пример 1: Пример анализатора @Deprecated

class Main {
  /**
   * @deprecated
   * Этот метод弃用了, и его заменил newMethod()
   */
  @Deprecated
  public static void deprecatedMethod() { 
    System.out.println("Deprecated method"); 
  } 
  public static void main(String args[]) {
    deprecatedMethod();
  }
}

Результат вывода

Устаревший метод

2. @Override

@Override анализатор определяет метод подкласса, который перекрывает метод родительского класса с тем же именем, типом возвращаемого значения и списком параметров.

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

Пример 2: Пример аннотации @Override

class Animal {
  // Переопределение метода
  public void display(){
    System.out.println("Я животное");
  }
}
class Dog extends Animal {
  // Переопределение метода
  @Override
  public void display(){
    System.out.println("Я собака");
  }
  public void printMessage(){
    display();
  }
}
class Main {
  public static void main(String[] args) {
    Dog dog1 = new Dog();
    dog1.printMessage();
  }
}

Результат вывода

Я собака

В этом примере, создав объект класса Dog dog1, мы можем вызвать его метод printMessage(), после чего этот метод выполняет оператор display().

Поскольку метод display() определен в обоих классах, метод display() подкласса Dog будет перекрывать метод display() суперкласса Animal. Таким образом, вызывается метод подкласса.

3. @SuppressWarnings

Как следует из названия, @SuppressWarnings аннотация указывает компилятору на禁止 отображения предупреждений, генерируемых при выполнении программы.

Мы можем определить типы предупреждений, которые нужно отменить. Запрещенные предупреждения специфичны для компилятора, но предупреждения делятся на две категории:устаревшее и Не проверено.

Чтобы запретить отображение конкретной категории предупреждений, мы намеренно используем:

@SuppressWarnings("warningCategory")

Например,

@SuppressWarnings("deprecated")

Чтобы запретить отображение множества категорий предупреждений, мы намеренно используем:

@SuppressWarnings({"warningCategory1", "warningCategory2"})

Например,

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

Когда мы используем не рекомендованные элементы, deprecated категория указывает компилятору на禁止 отображения предупреждений.

Когда мы используем исходные типы, unchecked категория указывает компилятору на禁止 отображения предупреждений.

Итак, неопределенные предупреждения будут игнорироваться. Например,

@SuppressWarnings("someundefinedwarning")

Пример 3: Пример использования аннотации @SuppressWarnings

class Main {
  @Deprecated
  public static void deprecatedMethod() { 
    System.out.println("Deprecated method"); 
  } 
  
  @SuppressWarnings("deprecated")
  public static void main(String args[]) {
    Main depObj = new Main();
    depObj. deprecatedMethod();
  }
}

Результат вывода

Устаревший метод

В этом примере deprecatedMethod() был помечен как устаревший, и при его использовании будет выдаваться компиляторное предупреждение. Используя аннотацию @SuppressWarnings("deprecated"), мы можем избежать компиляторного предупреждения.

4. @SafeVarargs

Аннотация @SafeVarargs утверждает, что метод или конструктор с аннотацией не выполняет не безопасные операции с его переменными параметрами (изменяемыми параметрами).

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

До Java 9 мы могли использовать эту аннотацию только в final или static методах, так как их нельзя переопределить. Теперь мы можем использовать эту аннотацию и в частных методах.

Пример 4: Пример использования аннотации @SafeVarargs

import java.util.*;
class Main {
  private void displayList(List<String>... lists) {
    for (List<String> list : lists) {
      System.out.println(list);
    }
  }
  public static void main(String args[]) {
    Main obj = new Main();
    List<String> universityList = Arrays.asList("Tribhuvan University", "Kathmandu University");
    obj.displayList(universityList);
    List<String> programmingLanguages = Arrays.asList("Java", "C");
    obj.displayList(universityList, programmingLanguages);
  }
}

Предупреждения

Типовая безопасность: Возможное загрязнение стека через varargs параметрные списки
Типовая безопасность: Создается массив generic List<String> для varargs 
 параметр

Результат вывода

Примечание: Main.java использует не проверенные или опасные операции.
[Университет Tribhuvan, Университет Kathmandu]
[Университет Tribhuvan, Университет Kathmandu]
[Java, C]

Здесь List ... list specifies the type of a variable-length parameter of type List. Это означает, что метод displayList() может иметь ноль или несколько параметров.

Программа компилируется без ошибок, но при отсутствии аннотации @SafeVarargs будет выдаваться предупреждение.

При использовании аннотации @SafeVarargs в предыдущем примере

@SafeVarargs
 private void displayList(List<String>... lists) { ... }

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

5. @FunctionalInterface

Java 8 впервые ввел эту аннотацию @FunctionalInterface. Эта аннотация указывает, что тип, для которого она используется, является функциональным интерфейсом. Функциональный интерфейс может иметь только один абстрактный метод.

Пример 5: Пример аннотации @FunctionalInterface

@FunctionalInterface
public interface MyFuncInterface{
  public void firstMethod(); // это абстрактный метод
}

Если мы добавим еще один абстрактный метод, то

@FunctionalInterface
public interface MyFuncInterface{
  public void firstMethod(); // это абстрактный метод
  public void secondMethod(); // это вызовет компиляционную ошибку
}

Теперь, когда мы запустим программу, мы получим следующее предупреждение:

Неожиданная аннотация @FunctionalInterface
@FunctionalInterface ^ интерфейс MyFuncInterface не является функциональным интерфейсом
Найдены несколько не перекрывающихся абстрактных методов в интерфейсе MyFuncInterface

Использование аннотации @FunctionalInterface не является обязательным. Компилятор будет рассматривать любое интерфейс, удовлетворяющее определению функционального интерфейса, как функциональный интерфейс.

Цель использования этой аннотации - обеспечить, чтобы функциональный интерфейс имел только один абстрактный метод.

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

@FunctionalInterface
public interface MyFuncInterface{
  public void firstMethod(); // Это абстрактный метод
  default void secondMethod() { ... } 
  default void thirdMethod() { ... } 
}

Пользовательские аннотации

Мы также можем создавать свои собственные пользовательские аннотации.

ее грамматика такова:

[Access Specifier] @interface<AnnotationName> {         
  DataType <MethodName>() [default value];
}

Вот информация о пользовательских аннотациях, которую вам нужно знать:

  • Аннотации можно создавать, используя @interface после имени аннотации.

  • Аннотации могут иметь элементы,看起来像方法是,но они не реализованы.

  • Значение по умолчанию является опциональным. Параметр не может быть пустым значением.

  • Тип возвращаемого значения может быть примитивным,枚举,строка,имя класса или массив этих типов.

Пример 6: Пример пользовательской аннотации

@interface MyCustomAnnotation {
  String value() default "default value";
}
class Main {
  @MyCustomAnnotation(value = "w3codebox")
  public void method1() {
    System.out.println("Тестовый метод 1");
  }
  public static void main(String[] args) throws Exception {
    Main obj = new Main();
    obj.method1();
  }
}

Результат вывода

Тестовый метод 1

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

Мета-аннотации - это аннотации, применяемые к другим аннотациям.

1. @Retention

Аннотация @Retention определяет наиболее высокий уровень доступности этой аннотации.

ее грамматика такова:

@Retention(RetentionPolicy)

Есть три типа:

  • RetentionPolicy.SOURCE - Комментарии доступны только на уровне исходного кода и игнорируются компилятором.

  • RetentionPolicy.CLASS - Аннотация доступна компилятору на этапе компиляции, но Java Virtual Machine (JVM) егоignore.

  • RetentionPolicy.RUNTIME - Аннотация может быть использована JVM.

Например,

@Retention(RetentionPolicy.RUNTIME)
public @interface MyCustomAnnotation{ ... }

2. @Documented

По умолчанию, пользовательские аннотации не включены в официальную документацию Java. Чтобы включить аннотацию в документацию Javadoc, используйте аннотацию @Documented.

Например,

@Documented
public @interface MyCustomAnnotation{ ... }

3. @Target

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

ее грамматика такова:

@Target(ElementType)

ElementType может быть одним из следующих типов:

Тип элементаTarget
ElementType.ANNOTATION_TYPEТип аннотации
ElementType.CONSTRUCTORКонструктор
ElementType.FIELDПоле
ElementType.LOCAL_VARIABLEЛокальная переменная
ElementType.METHODМетод
ElementType.PACKAGEПакет
ElementType.PARAMETERПараметры
ElementType.TYPEИспользуется для описания класса, интерфейса (включая тип аннотации) или объявления enum.

Например,

@Target(ElementType.METHOD)
public @interface MyCustomAnnotation{ ... }

В этом примере мы ограничили использование этой аннотации методами.

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

4. @Inherited

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

ее грамматика такова:

@Inherited

Например,

@Inherited
public @interface MyCustomAnnotation { ... }
@MyCustomAnnotation
public class ParentClass{ ... }
public class ChildClass extends ParentClass { ... }

5. @Repeatable

Аннотация с меткой @Repeatable может быть применена несколько раз к одному и тому же заявлению.

@Repeatable(Universities.class)
public @interface University {
  String name();
}

Значение, определенное в аннотации @Repeatable, является контейнерной аннотацией. Контейнерная аннотация имеет переменную значения (value) типа массива с повторяющимися аннотациями, как указано выше. Здесь Universities содержит аннотационные типы.

public @interface Universities {
  University[] value();
}

Теперь, аннотация @University может использоваться несколько раз в одном объявлении.

@University(name = "TU")
@University(name = "KU")
private String uniName;

Если нужно извлечь данные аннотации, можно использоватьОтражение.

Чтобы извлечь значение аннотации, мы используем методы getAnnotationsByType() или getAnnotations() из反射ного API.