Java 注解,也称为 Java Annotations,是一种元数据(Meta-data)标记语言,它在 Java 代码中添加了额外的信息和说明。注解可以用于类、方法、变量、参数、包等各种程序成分上,以达到不同的应用场景。

Java 注解是从 Java 5 开始引入的,在当时就被广泛认为是 Java 语言一个非常重要的新特性之一。Java 注解通常使用 @ 符号进行声明,其基本语法如下:

@<AnnotationName>(<AttributeValue>)

其中,AnnotationName 是注解的名称,AttributeValue 则是注解的属性值。注解可以没有属性,此时括号中的内容可以省略。

自定义注解的语法与定义接口类似,需要使用 @interface 关键字进行声明。例如:

public @interface MyAnnotation {
    String value();
}

上述代码定义了一个名为 MyAnnotation 的注解,并定义了一个名为 value 的属性,其返回类型为 String

当我们定义一个注解时,可以使用元注解(Meta-annotation)来指定注解的生命周期、作用范围等属性。以下是几个常见的元注解:

  • @Retention:指定注解的生命周期。可选值有三种:SOURCECLASSRUNTIME。其中,SOURCE 表示该注解只存在于源代码中,在编译后被丢弃;CLASS 表示该注解在编译后会被保留在 class 文件中,但是在运行时无法获取;RUNTIME 表示该注解在运行时可以被反射机制获取到,默认值为 CLASS
  • @Target:指定注解的作用范围。可选值包括 ANNOTATION_TYPECONSTRUCTORFIELDLOCAL_VARIABLEMETHODPACKAGETYPE。其中,TYPE 表示该注解可以用于类、接口和枚举上。
  • @Documented:指定该注解是否包含在 JavaDoc 文档中。
  • @Inherited:指定该注解能否被子类继承。

接下来,我们通过一个具体的示例来说明如何定义和使用注解。

假设我们要为一个类添加日志输出功能。首先,我们可以定义一个 @Log 注解,用于标记需要输出日志的方法:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Log {
    String value() default "";
}

上述代码中,我们使用了 @Target@Retention 元注解来指定了 @Log 注解的作用范围和生命周期。此外,我们还定义了一个名为 value 的属性,其默认值为空字符串。

接下来,我们可以在需要输出日志的方法上添加 @Log 注解,并传入具体的日志信息:

public class MyClass {
    @Log("start my method")
    public void myMethod() {
        // do something
    }
}

在上述代码中,我们为 myMethod 方法添加了 @Log 注解,其中传入了具体的日志信息。

最后,我们使用反射机制来获取并处理 @Log 注解:

MyClass obj = new MyClass();
Method method = obj.getClass().getMethod("myMethod");

if (method.isAnnotationPresent(Log.class)) {
    Log log = method.getAnnotation(Log.class);
    System.out.println(log.value());
}

在上述代码中,我们首先创建了 MyClass 类的实例 obj,然后通过 getClass() 方法获取其对应的 Class 对象。接着,我们使用 getMethod() 方法获取 myMethod 方法的 Method 对象,并判断其是否存在 @Log 注解。如果存在,我们使用 getAnnotation() 方法获取 @Log 注解对象,并输出其中的日志信息。

通过上述示例,我们可以看出注解在 Java 代码中的应用非常灵活,可以满足很多特殊需求。例如,我们可以通过自定义注解为某些方法添加事务支持、权限校验等功能,在实际的开发中具有很大的应用价值。

Java 中内置的注解非常多,以下是其中常用的几个注解及其作用:

  • @Override:标记方法重写父类中的方法。如果该注解被用在一个没有重写父类方法的方法上就会导致编译错误。
  • @Deprecated:标记某个程序元素(类、方法等)已过时,通常是由于它不再安全或有效,建议不要再使用它。
  • @SuppressWarnings:抑制编译器警告信息。该注解可以用于类、方法、变量等任何程序成分上,以屏蔽指定类型的编译器警告。
  • @FunctionalInterface:标记接口为函数式接口。函数式接口是只具有一个抽象方法的接口,在 Java 8 中引入了 Lambda 表达式后,函数式接口得到了广泛应用。
  • @SafeVarargs:标记方法是类型安全的可变参数方法,即保证方法不会对传入的可变参数数组进行不安全的操作。
  • @SuppressWarnings:抑制编译器警告信息。该注解可以用于类、方法、变量等任何程序成分上,以屏蔽指定类型的编译器警告。
  • @FunctionalInterface:标记接口为函数式接口。函数式接口是只具有一个抽象方法的接口,在 Java 8 中引入了 Lambda 表达式后,函数式接口得到了广泛应用。
  • @SafeVarargs:标记方法是类型安全的可变参数方法,即保证方法不会对传入的可变参数数组进行不安全的操作。
  • @SuppressWarnings:抑制编译器警告信息。该注解可以用于类、方法、变量等任何程序成分上,以屏蔽指定类型的编译器警告。
  • @FunctionalInterface:标记接口为函数式接口。函数式接口是只具有一个抽象方法的接口,在 Java 8 中引入了 Lambda 表达式后,函数式接口得到了广泛应用。
  • @SafeVarargs:标记方法是类型安全的可变参数方法,即保证方法不会对传入的可变参数数组进行不安全的操作。
  • @SuppressWarnings:抑制编译器警告信息。该注解可以用于类、方法、变量等任何程序成分上,以屏蔽指定类型的编译器警告。
  • @FunctionalInterface:标记接口为函数式接口。函数式接口是只具有一个抽象方法的接口,在 Java 8 中引入了 Lambda 表达式后,函数式接口得到了广泛应用。
  • @SafeVarargs:标记方法是类型安全的可变参数方法,即保证方法不会对传入的可变参数数组进行不安全的操作。