23 - Java 注解

发布于:2025-02-11 ⋅ 阅读:(49) ⋅ 点赞:(0)

注解

  • 从 Java 5 开始出现
  • Annotaticm 能被用来为程序元素( 类、方法、成员变量等)设置元数据
  • 所有注解都隐式继承了 Annotation java.lang.annotation.Annotation 接口

基本 Annotation

在 java.lang 包下
  • @Override:限定重写父类方法
  • @Deprecated:标示已过时(与文档注释中的 @deprecated 标记的作用基本相同)
  • @SuppressWarnings("变量值") :抑制编译器警告(常见的变量值:unused, rawtypes, unchecked, serial, deprecation, all)
  • @SafeVarargs: 抑制编译器“堆污染”警告(Java 7 新增)
  • @FunctionalInterface: 函数式接口(接口中只有一个抽象方法)(Java 8 新增)

JDK 的元 Annotation

在 java.lang.annotation 包下,用于修饰其它的 Annotation 定义
  • @Target :用于指定被修饰的注解能用于修饰哪些程序元素常量值封装在 ElementType 枚举类中:TYPE、FIELD、CONSTRUCTOR、METHOD、LOCAL_VARIABLE、PACKAGE、PARAMETER、ANNOTATION_TYPE
  • @Retention:用于指定被修饰的注解可以保留多长时间常量值封装在 RetentionPolicy 枚举类中:SOURCE、CLASS(默认值)、RUNTIME
  • @Documented:其修饰的注解会保存到 API 文档中
  • @Inherited:其修饰的注解可以被子类所继承

自定义 Annotation

  • Annotation 中的属性以无参数的抽象方法的形式来定义
  • 属性的类型只能是基本类型、String、Class、annotation、枚举及这些类型一维数组
  • 在定义 Annotation 的属性时可以使用 default 为其指定默认值
  • 使用带属性的注解时,必须为该注解的所有没有默认值的属性指定值
  • 对于 Annotation 中变量名为 value属性,在使用该注解时可以直接在该注解后的括号里指定 value 属性的值,无须使用“value = 变量值”的形式
public @interface MyTag1 {
    String name();
    int age();
}
// 使用
@MyTag1(name="xx", age=6)
public @interface MyTag2 {
    // 使用 default 为两个成员变量指定初始值
    String name() default "admin";
    int age() default 17;
}
// 使用
@MyTag2
// 获取程序元素上的注解 @MyTag2 的成员变量的值
程序元素.getAnnotation(MyTag2.Class).成员变量名()

通过反射获取程序元素的 Annotation 信息

  • 只能提取使用了@Retention(RetentionPolicy.RUNTIME) 修饰的注解
  • AnnotatedElement 接口是所有程序元素(Class、Constructor、Field、Method、Package ) 的父接口
  • AnnotatedElement 接口中的方法

编译时处理 Annotation

  • 注解处理工具 APT(Annotation Processing Tool)

常用注解

在Java中, @Retention@Target是两个非常重要的元注解(meta-annotation),它们用于定义其他注解的行为和特性。
下面我将详细解释这两个注解以及它们如何结合使用。

@Target 注解

@Target注解用于指定一个注解可以应用的Java元素类型。它带有一个 value元素,该元素是一个 ElementType枚举类型的数组,用于列出注解可以应用的所有元素类型。
例如,如果你想要创建一个只能应用于方法上的注解,你可以这样定义:
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
public @interface MyMethodAnnotation {
    // 注解内容
}
在这个例子中, MyMethodAnnotation只能被应用于方法上。如果你尝试将它应用于其他类型的元素(如类、字段等),编译器将会报错。

@Retention 注解

@Retention注解用于指定注解的保留策略,即注解在何时有效。它带有一个 value元素,该元素是 RetentionPolicy枚举类型的一个实例。 RetentionPolicy有三个可能的值:
  • SOURCE:注解只在源代码中存在,编译成字节码文件时会被丢弃。这种注解通常用于标记,对代码的运行没有影响。
  • CLASS:注解在源代码和字节码文件中都存在,但在运行时不会被加载到JVM中。这是默认的保留策略。
  • RUNTIME:注解在源代码、字节码文件中存在,并且在运行时可以被加载到JVM中,因此可以通过反射机制读取注解的信息。
例如,如果你想要创建一个在运行时仍然有效的注解,你可以这样定义:
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface MyRuntimeAnnotation {
    // 注解内容
}

结合使用@Target@Retention

在实际应用中,你通常会结合使用 @Target@Retention来定义注解的行为和特性。
例如,你可以创建一个只能应用于方法上并且在运行时仍然有效的注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMethodRuntimeAnnotation {
    String value() default "default value";
}
在这个例子中,MyMethodRuntimeAnnotation 注解只能被应用于方法上,并且在运行时可以通过反射机制读取其信息。
你可以这样使用这个注解:
public class MyClass {

    @MyMethodRuntimeAnnotation(value = "Test method")
    public void myMethod() {
        // 方法实现
    }
}
然后,在运行时,你可以通过反射获取 myMethod 方法的注解,并读取其 value 元素的值:
import java.lang.reflect.Method;

public class AnnotationTest {
    public static void main(String[] args) throws Exception {
        Method method = MyClass.class.getMethod("myMethod");
        if (method.isAnnotationPresent(MyMethodRuntimeAnnotation.class)) {
            MyMethodRuntimeAnnotation annotation = method.getAnnotation(MyMethodRuntimeAnnotation.class);
            System.out.println("Annotation value: " + annotation.value());
        }
    }
}
这段代码将输出:Annotation value: Test method 。这证明了 MyMethodRuntimeAnnotation 注解在运行时是有效的,并且可以通过反射机制读取其信息。

网站公告

今日签到

点亮在社区的每一天
去签到