第十四章笔记整理
这章详细介绍了 Java 中的 Annotation(注解)技术,涵盖了从 JDK 5 引入的基本概念到 Java 8 的新特性。Annotation 本质上是一种元数据,它为代码提供了额外的信息,这些信息可以在编译时、类加载时或运行时被读取和处理,而不会影响代码本身的执行逻辑。
-
基本概念与作用
定义:Annotation 是代码中的特殊标记,可以修饰包、类、方法、变量等程序元素。
核心机制:Annotation 本身不会改变程序逻辑,必须通过配套的工具(APT, Annotation Processing Tool)来提取和处理其中的信息,才能实现额外功能。
本质:Annotation 是一个接口,程序可以通过反射来获取指定程序元素的 Annotation 对象。 -
5 个基本 Annotation
Java 在 java.lang 包下提供了 5 个基本的内置注解,它们的具体作用如下:
@Override:用于限定重写父类方法。它强制子类必须覆盖父类的方法,这能有效帮助开发者避免因方法名拼写错误(如将 info 写成 inf0)而导致的逻辑错误。
@Deprecated:用于标示已过时。当其他程序使用被该注解修饰的类或方法时,编译器会给出警告提示,提醒开发者该元素已不再推荐使用。
@SuppressWarnings:用于抑制编译器警告。它可以指示被修饰的程序元素(及其子元素)取消显示指定的编译器警告,常用于处理未使用泛型等场景。
@SafeVarargs:这是 Java 7 新增的注解,用于抑制“堆污染”警告。它专门修饰参数个数可变(Varargs)且类型为泛型的方法或构造器,告诉编译器该方法是安全的。
@FunctionalInterface:这是 Java 8 新增的注解,用于声明函数式接口。它会检查接口是否只包含一个抽象方法,主要用于配合 Lambda 表达式使用。 -
4 个元 Annotation (Meta-Annotation)
元注解用于修饰其他注解的定义,位于 java.lang.annotation 包下:
@Retention (保留策略):指定注解保留多长时间。
SOURCE:仅保留在源码中,编译时丢弃。
CLASS:保留在 class 文件中(默认),运行时 JVM 不可获取。
RUNTIME:保留在 class 文件中,运行时 JVM 可获取(通过反射)。
@Target (作用目标):指定注解能修饰哪些程序单元(如 METHOD, FIELD, TYPE, PARAMETER 等)。
@Documented:指定该注解将被 javadoc 工具提取到 API 文档中。
@Inherited:指定该注解具有继承性,子类会自动继承父类使用的该注解。 -
自定义 Annotation 与反射
定义语法:使用 @interface 关键字定义。
成员变量:以无参方法的形式声明(如 String name();)。
默认值:使用 default 关键字指定。
分类:
标记 Annotation:不包含成员变量,仅利用其存在与否提供信息(如 @Override)。
元数据 Annotation:包含成员变量,可接受更多元数据。
提取信息:
通过反射(java.lang.reflect)获取。
只有 @Retention(RetentionPolicy.RUNTIME) 的注解才能在运行时被获取。
核心接口是 AnnotatedElement(Class, Method, Field 等均实现此接口),通过 getAnnotation() 等方法访问。 -
Java 8 新特性
重复注解 (@Repeatable):允许在同一个地方使用多个相同类型的注解。
实现机制:需要一个“容器注解”(包含一个数组类型的 value 成员)来包裹多个重复的注解。
类型注解 (Type Annotation):新增 ElementType.TYPE_USE 和 ElementType.TYPE_PARAMETER。
允许注解出现在任何使用类型的地方,如创建对象 (new @NotNull String())、类型转换、实现接口等,增强了代码的健壮性检查。 -
编译时处理 (APT)
APT (Annotation Processing Tool):在编译期间扫描和处理源代码中的注解。
作用:可以根据注解生成额外的源文件或其他文件(如 XML 配置文件),简化开发工作。
实现:通过实现 Processor 接口或继承 AbstractProcessor 类,配合 javac -processor 命令使用。