Java 预定义的注解

Java 注解是程序源代码的元数据。在本教程中,我们将借助示例了解几个常用的 Java 预定义的注解。

在本教程中,我们将借助示例了解几个常用的 Java 预定义的注解。包括:

  • @Deprecated
  • @Override
  • @SuppressWarnings
  • @SafeVarargs
  • @FunctionalInterface

如果您不知道什么是注解,请访问 Java 注解教程。

@Deprecated

@Deprecated 注解是一个标记注解,用来指示元件(类,方法,字段等)已过时,可以被一个较新的元件替换。

当程序使用已声明为弃用的元件时,编译器会生成警告。

我们使用 Javadoc @deprecated 标记在文档中生成元件被启用的说明。。

示例 1:@Deprecated 注解示例

public class Main {
  /**
   * @deprecated
   * 这个方法已过时,请使用 newMethod() 代替
   */
  @Deprecated
  public static void deprecatedMethod() {
    System.out.println("Deprecated method");
  }

  public static void main(String args[]) {
    deprecatedMethod();
  }
}

@Override

@Override 注解指定了一个子类的方法覆盖了父类的方法。

覆盖方法时不强制使用 @Override。但是,如果我们使用了它,如果子类的方法不符合覆盖方法的规则,编译器会给出错误。

示例 2:@Override 注解示例

public class Animal {

  // overridden method
  public void display(){
    System.out.println("I am an animal");
  }
}

public class Dog extends Animal {

  // overriding method
  @Override
  public void display(){
    System.out.println("I am a dog");
  }

  public void printMessage(){
    display();
  }
}

public class Main {
  public static void main(String[] args) {
    Dog dog1 = new Dog();
    dog1.printMessage();
  }
}

输出

I am a dog

@SuppressWarnings

顾名思义, @SuppressWarnings 注解指示编译器抑制程序执行时生成的警告。

我们可以指定要抑制的警告类型。可以抑制的警告是特定于编译器的,有两类警告:

  • deprecation: 抑制那些使用了标注为 @Deprecated 元件的警告。
  • unchecked: 抑制那些未检查类型的警告。

SuppressWarnings 参数值可以是字符串或者字符串数组,例如,

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

示例 3:@SuppressWarnings 注解示例

public 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()@Deprecated 标记为已弃用,并且在使用时会给出编译器警告。通过使用 @SuppressWarnings("deprecated") 注解,我们可以避免编译器警告。

@SafeVarargs

@SafeVarargs 注解用于抑制编译时因为可变参数中带有泛型引起类型模糊而给出的警告。

我们只能在不能被覆盖的方法或构造函数上使用这个注解。这是因为覆盖它们的方法可能会执行不安全的操作。

在 Java 9 之前,我们只能在 finalstatic 方法上使用此注解,因为它们不能被覆盖。我们现在也可以将此注解用于私有方法。

示例 4:@SafeVarargs 注解示例

import java.util.*;

public 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);
  }
}

当我们使用 javac -Xlint:unchecked .\Main.java 编译程序时,会得到如下警告

.\Main.java:5: 警告: [unchecked] 参数化 vararg 类型List<String>的堆可能已受污染
  private void displayList(List<String>... lists) {
                                           ^
.\Main.java:15: 警告: [unchecked] 对于类型为List<String>[]的 varargs 参数, 泛型数组创建未经过检查
    obj.displayList(universityList);
                   ^
.\Main.java:18: 警告: [unchecked] 对于类型为List<String>[]的 varargs 参数, 泛型数组创建未经过检查
    obj.displayList(universityList, programmingLanguages);
                   ^
3 个警告

警告并不影响程序正常运行,程序的输出

[Tribhuvan University, Kathmandu University]
[Tribhuvan University, Kathmandu University]
[Java, C]

此处, displayList() 方法的参数 List<String>... lists 指定了方法的参数位可变长度参数。这意味着方法可以有零个或多个参数。

上述程序编译时没有错误,但在未使用 @SafeVarargs 注解时会产生上面的警告信息。

当我们在上面的例子中使用 @SafeVarargs 注解后,

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

我们得到相同的输出,但没有任何警告。当我们使用这个注解时, unchecked 的警告也会被抑制。

@FunctionalInterface

Java 8 首先引入了这个 @FunctionalInterface 注解。这个注解表明使用它的类型是一个函数式接口。

函数式接口需要满足以下条件:

  1. 函数式接口必须是一个接口。
  2. 函数式接口只能有一个抽象方法。
  3. 函数式接口可以有默认方法和静态方法。

示例 5:@FunctionalInterface 注解示例

@FunctionalInterface
public interface MyFuncInterface{
  public void firstMethod();
}

如果我们添加另一个抽象方法,让我们说

@FunctionalInterface
public interface MyFuncInterface{
  public void firstMethod();
  public void secondMethod();
}

现在,当我们运行程序时,我们将收到以下警告:

.\Main.java:1: 错误: 意外的 @FunctionalInterface 注释
@FunctionalInterface
^
  MyFuncInterface 不是函数接口
    在 接口 MyFuncInterface 中找到多个非覆盖抽象方法
1 个错误

使用 @FunctionalInterface 注解不是强制性的。但是一旦标注了此注解,编译器就要求被标注的类型是一个函数时接口。