一句话说透Java里面的注解

133 阅读2分钟

注解(Annotation)  就像代码里的「便利贴」,用来给类、方法、字段等贴标签,告诉编译器、工具或运行时环境一些额外信息。它本身不改变代码逻辑,但可以通过其他工具读取这些标签来触发特定行为。


一、注解的三大作用

  1. 给编译器发指令

    • 例子:@Override

    • 作用:检查方法是否真的重写了父类方法,没重写就报错。

    • 代码示例:

      @Override  
      public String toString() { return "重写成功"; }  
      
  2. 给工具/框架发信号

    • 例子:@Test(JUnit)、@Autowired(Spring)

    • 作用:告诉测试框架“这是测试方法”,或让Spring自动注入依赖。

    • 代码示例:

      @Test  
      public void testLogin() { /* 测试代码 */ }  
      
  3. 生成代码或配置文件

    • 例子:Lombok的@Data

    • 作用:编译时自动生成getter/setter方法。

    • 代码示例:

      @Data  
      public class User {  
          private String name;  
          private int age;  
      }  
      

二、注解的本质与定义

1. 注解的本质
  • 注解是一个接口,继承自java.lang.annotation.Annotation

  • 定义方式:用 @interface 关键字。

    public @interface MyAnnotation {  
        String value() default "";  // 参数(类似方法)  
        int priority() default 0;  
    }  
    
2. 元注解(注解的注解)
元注解作用示例
@Target指定注解能贴在哪里@Target(ElementType.METHOD)
@Retention指定注解保留到哪个阶段@Retention(RetentionPolicy.RUNTIME)
@Documented让注解出现在Javadoc中@Documented
@Inherited允许子类继承父类的注解@Inherited

示例:定义一个运行时生效的类注解

@Target(ElementType.TYPE)  
@Retention(RetentionPolicy.RUNTIME)  
public @interface Table {  
    String name() default ""; // 数据库表名  
}  

三、注解的读取与处理

1. 编译时处理
  • APT(Annotation Processing Tool) :在编译时扫描注解,生成代码或报告。

    • 例子:Lombok生成getter/setter。
2. 运行时处理
  • 反射机制:通过反射API读取注解信息。

    Class<?> clazz = User.class;  
    if (clazz.isAnnotationPresent(Table.class)) {  
        Table table = clazz.getAnnotation(Table.class);  
        System.out.println("表名:" + table.name());  
    }  
    
3. 框架集成
  • Spring@Component注解标记Bean,容器启动时扫描并管理。
  • JUnit@Test标记测试方法,运行时执行测试。

四、常见注解场景

场景常用注解作用
代码检查@Override@Deprecated编译器检查或标记过时代码
依赖注入@Autowired@ResourceSpring自动装配Bean
Web开发@Controller@RequestMappingSpring MVC处理HTTP请求
数据校验@NotNull@SizeHibernate校验字段合法性

五、总结口诀

「注解就像便利贴,贴在代码传信息
编译检查靠元注,运行时用反射读
框架工具认标签,自动生成少写码!」

附:自测问题

  1. 如何定义一个只能用在方法上、且在运行时有效的注解?

    @Target(ElementType.METHOD)  
    @Retention(RetentionPolicy.RUNTIME)  
    public @interface LogExecutionTime {}  
    
  2. 如何通过反射获取类上的注解?

    Class<?> clazz = MyClass.class;  
    MyAnnotation annotation = clazz.getAnnotation(MyAnnotation.class);