跳到主要内容

Java 注解

提示
  1. Java 注解基础:Java 注解是源代码的元数据,提供额外信息给编译器但不影响程序执行。常以 @AnnotationName 形式出现,如 @Override
  2. 注解类型和格式:注解可以是标记注解(无成员)、单元素注解(一个元素)或多元素注解(多个成员)。注解可以放在声明上方或作为类型注解使用。
  3. 注解用途和类型:注解用于编译器指令(检测错误、抑制警告),编译时和运行时指令。常见注解类型包括预定义注解(如 @Deprecated)、元注解(如 @Retention)和自定义注解。

Java 注解是我们程序源代码的元数据(关于数据的数据)。

它们为编译器提供有关程序的额外信息,但并不是程序本身的一部分。这些注解不会影响编译后程序的执行。

注解以 @ 开头。其语法为:

@AnnotationName

让我们以 @Override 注解为例。

@Override 注解指定带有此注解的方法覆盖了具有相同方法名称、返回类型和参数列表的超类方法。

覆盖方法时使用 @Override 并不是强制性的。但是,如果使用它,当覆盖方法时出现错误(如参数类型错误)时,编译器会给出错误提示。

示例 1:@Override 注解示例

class Animal {
public void displayInfo() {
System.out.println("我是一只动物。");
}
}

class Dog extends Animal {
@Override
public void displayInfo() {
System.out.println("我是一只狗。");
}
}

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

输出

我是一只狗。

在此示例中,方法 displayInfo() 在超类 Animal 和子类 Dog 中都存在。当调用此方法时,将调用子类的方法而不是超类中的方法。

注解格式

注解还可以包含元素(成员/属性/参数)。

1. 标记注解

标记注解不包含成员/元素。它仅用于标记声明。

其语法为:

@AnnotationName()

由于这些注解不包含元素,因此可以省略括号。例如,

@Override

2. 单元素注解

单元素注解只包含一个元素。

其语法为:

@AnnotationName(elementName = "elementValue")

如果只有一个元素,通常将该元素命名为 value

@AnnotationName(value = "elementValue")

在这种情况下,也可以省略元素名称。元素名称默认为 value

@AnnotationName("elementValue")

3. 多元素注解

这些注解包含多个用逗号分隔的元素。

其语法为:

@AnnotationName(element1 = "value1", element2 = "value2")

注解放置位置

注解可以通过放置在声明之上来标记任何声明。从 Java 8 开始,注解也可以放在类型之前。

1. 在声明上方

如上所述,Java 注解可以放在类、方法、接口、字段和其他程序元素声明的上方。

示例 2:@SuppressWarnings 注解示例

import java.util.*;

class Main {
@SuppressWarnings("unchecked")
static void wordsList() {
ArrayList wordList = new ArrayList<>();

// 这会导致一个未检查的警告
wordList.add("mashangxue123");

System.out.println("单词列表 => " + wordList);
}

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

输出

单词列表 => [mashangxue123]

如果上述程序没有使用 @SuppressWarnings("unchecked") 注解编译,编译器仍会编译程序,但会产生如下警告:

Main.java 使用了未检查或不安全的操作。
单词列表 => [mashangxue123]

我们收到警告

Main.java 使用了未检查或不安全的操作

是因为以下语句。

ArrayList wordList = new ArrayList<>();

这是因为我们没有定义数组列表的泛型类型。我们可以通过在尖括号 <> 内指定泛型来修复这个警告。

ArrayList<String> wordList = new ArrayList<>();

2. 类型注解

在 Java 8 之前,注解只能应用于声明。现在,类型注解也可以使用。这意味着我们可以在使用类型的任何地方放置注解。

构造函数调用

new @Readonly ArrayList<>()

类型定义

@NonNull String str;

此声明指定非空变量 strString 类型,以避免 NullPointerException

@NonNull List<String> newList;

此声明指定一个非空的 String 类型列表。

List<@NonNull String> newList;

此声明指定一个由非空 String 类型值组成的列表。

类型转换

newStr = (@NonNull String) str;

extends 和 implements 子句

class Warning extends @Localized Message

throws 子句

public String readMethod() throws @Localized IOException

类型注解使 Java 代码能够更好地进行分析,并提供更强的类型检查。

注解类型

  1. 预定义注解

    1. @Deprecated
    2. @Override
    3. @SuppressWarnings
    4. @SafeVarargs
    5. @FunctionalInterface
  2. 元注解

    1. @Retention
    2. @Documented
    3. @Target
    4. @Inherited
    5. @Repeatable
  3. 自定义注解

    这些注解类型在 Java 注解类型 教程中有详细描述。

注解的使用

  • 编译器指令 - 注解可用于向编译器提供指令,检测错误或抑制警告。内置的注解 @Deprecated@Override@SuppressWarnings 用于这些目的。
  • 编译时指令 - 这些注解提供的编译时指令有助于软件构建工具生成代码、XML 文件等。
  • 运行时指令 - 一些注解可以定义为在运行时向程序提供指令。这些注解通过 Java 反射访问。