@Target的核心用途是在编译期声明注解的适用位置,如@Target({ElementType.METHOD})限定仅方法可用,@Target({ElementType.TYPE})涵盖类、接口、枚举,多类型用数组组合,TYPE_USE和TYPE_PARAMETER需显式声明以支持泛型等场景。

@Target 的核心用途不是“运行时限制”,而是**在编译期明确声明:这个注解允许写在哪种程序元素上**。它像一张“使用说明书”,告诉 javac 编译器——只允许标注在方法上?那就只准标在 void doSomething() 前;只允许标在类上?那就只接受 @MyAnno public class X { }。写错位置,编译直接失败,根本不会生成 class 文件。
怎么限定只能用在方法上
用 @Target({ElementType.METHOD}) 即可。定义后:
- ✅ 允许:
@MyAnno public void save() { } - ❌ 编译报错:
@MyAnno public class Service { }(提示 “not applicable to this kind of declaration”) - ⚠️ 注意:必须带大括号,
@Target(ElementType.METHOD)是语法错误,会编译不通过
怎么限定只能用在类(或接口、枚举)上
用 @Target({ElementType.TYPE})。这里的 TYPE 涵盖三类:
- 普通类:
@MyAnno public class User { } - 接口:
@MyAnno public interface Repository { } - 枚举:
@MyAnno public enum Status { OK, ERROR } - ⚠️ 不包括字段、方法、参数——哪怕加了也会被编译器拦截
想同时支持方法和类,该怎么写
把多个 ElementType 用数组形式并列声明:
@Target({ElementType.METHOD, ElementType.TYPE})- ✅ 允许:
@MyAnno public class A { }和@MyAnno public void init() { } - ❌ 仍禁止:
@MyAnno private String name;(字段不在允许列表中) - ? 小技巧:Spring 的
@Component就是@Target({TYPE}),而@Value是@Target({FIELD, METHOD, PARAMETER})
容易踩坑的两个 Java 8+ 类型
如果希望注解也能出现在泛型或类型使用处(比如 List 或 new @Immutable ArrayList()),不能只靠 METHOD 或 TYPE:
-
ElementType.TYPE_USE:覆盖所有“用到类型的地方”,但 不自动包含类声明或方法声明 - 正确写法:
@Target({ElementType.METHOD, ElementType.TYPE_USE}) -
ElementType.TYPE_PARAMETER:专用于泛型形参,如class Box,需单独声明才生效

















