@target是java元注解,用于限定自定义注解的适用位置,仅在编译期校验——写错位置则javac直接报错;常用elementtype包括type(类/接口/枚举)、method(方法)、field(字段)、parameter(参数)等。

@Target 是 Java 中的元注解,用来声明自定义注解能写在哪些位置。它不控制运行时行为,只在编译期起作用——写错地方,javac 直接报错,连 class 文件都不会生成。
最常用:TYPE、METHOD、FIELD、PARAMETER
这四个是日常开发中 90% 场景会用到的:
-
TYPE:类、接口、枚举、记录(record)、注解类型(
@interface)本身。比如 Spring 的@Component就是@Target({ElementType.TYPE}),所以只能标在类/接口上,不能标在方法里。 -
METHOD:仅限方法声明处,包括 public/private/static/default 方法,但不包括构造器。日志、权限、事务类注解(如
@Loggable、@Transactional)多用这个。 -
FIELD:成员变量(含
private String name;)、静态常量(public static final int MAX = 1;)、枚举常量(RED, GREEN)。Spring 的@Autowired、校验框架的@NotNull常限定在此。 -
PARAMETER:方法或构造器的形参。比如
void save(@Valid User user)中的user;Spring 的@PathVariable、@RequestBody也属此类。
构造与局部:CONSTRUCTOR 和 LOCAL_VARIABLE
这两个偏底层,但有明确语义边界:
-
CONSTRUCTOR:只允许标注在构造器上,例如
@Inject public Service(Config cfg) { }。适合依赖注入或强制初始化逻辑的标记。 -
LOCAL_VARIABLE:仅限局部变量声明那一行,如
final @NonNull String s = getName();。注意不是赋值语句,也不是 for 循环里的i++,而是int i = 0;这种定义位置。常用于静态分析工具做空值检查。
结构级与元级:PACKAGE 和 ANNOTATION_TYPE
它们面向的是代码组织层级,而非具体逻辑单元:
-
PACKAGE:只能写在
package-info.java文件顶部,给整个包加元数据。比如统一标记包已废弃:@Deprecated package com.example.old;。 -
ANNOTATION_TYPE:专指另一个注解类型的声明本身,即
@interface MyAnno { }这一行。不是用来标在别人身上,而是标在“注解的定义”上——比如给注解加文档说明或分类标签。
泛型与类型使用:TYPE_PARAMETER 和 TYPE_USE
Java 8 引入,专为类型安全增强设计,需显式声明才生效:
-
TYPE_PARAMETER:作用于泛型形参声明,如
class Box { }中的T。不能靠TYPE或METHOD自动覆盖。 -
TYPE_USE:覆盖所有“使用类型”的位置,包括:
– 泛型实参:List
– 数组维度:@NonNull String[]
– 强制转换:(@NonNull Object) obj
– instanceof 右侧:obj instanceof @Immutable List>
– throws 子句:void read() throws @IoChecked IOException
配合 Checker Framework 等工具做编译期类型检查时必须用它。











