Annotation的理解与运用

15 篇文章 0 订阅
13 篇文章 0 订阅

一、引言

     作为Java开发人员,注解想必大家都不会陌生,在日常的工作,我们也会经常用到注解,java注解是在JDK5开始引入的新特性,它很好简化了代码,解耦程序;本文我将从注解的语法和特性进行总结.

 

二、注解的语法特性

1. 注解的声明

首先我们来看一个@Test注解的源码


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {

} 

由上的例子,可看到一个注解由三个主要元素组成,@interface,@Retention,@Target,对于@Target@Retention是由Java提供的元注解,所谓元注解就是标记其他注解的注解; 它们的作用如下:

  1. @interface,声明一个注解,所有的注解都要通过interface来声明
  2. @Target,声明注解作用的范围,参数ElementType.METHOD,表明该注解只能用在方法上,ElementType的完整定义如下
public enum ElementType {
    /**标明该注解可以用于类、接口(包括注解类型)或enum声明*/
    TYPE,

    /** 标明该注解可以用于字段(域)声明,包括enum实例 */
    FIELD,

    /** 标明该注解可以用于方法声明 */
    METHOD,

    /** 标明该注解可以用于参数声明 */
    PARAMETER,

    /** 标明注解可以用于构造函数声明 */
    CONSTRUCTOR,

    /** 标明注解可以用于局部变量声明 */
    LOCAL_VARIABLE,

    /** 标明注解可以用于注解声明(应用于另一个注解上)*/
    ANNOTATION_TYPE,

    /** 标明注解可以用于包声明 */
    PACKAGE,

    /**
     * 标明注解可以用于类型参数声明(1.8新加入)
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * 类型使用声明(1.8新加入)
     * @since 1.8
     */
    TYPE_USE
}

 

   3. @Retention,约束注解的声明周期,分别是源码级(source),类文件级别(class),运行时级别 (runtime),具体含义如下: 

  • SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里)
  • CLASS:注解在class文件中可用,但会被VM丢弃(该类型的注解信息会保留在源码里和class文件里,在执行的时候,不会加载到虚拟机中),请注意,当注解未定义Retention值时,默认值是CLASS,如Java内置注解,@Override、@Deprecated、@SuppressWarnning等
  • RUNTIME:注解信息将在运行期(JVM)也保留,因此可以通过反射机制读取注解的信息(源码、class文件和执行的时候都有注解的信息),如SpringMvc中的@Controller、@Autowired、@RequestMapping等。  

2. 注解元素及其数据类型

很多注解内部是没有定义任何元素,如@Override注解,这种类型的注解称为标记注解(marker annotation),但往往我们需要注解内部定义一些元素,方便提供更强大的功能,如@Controller注解

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
    String value() default "";  //定义了String类型的value元素,默认值为空字符串
}

注解内部元素支持的数据类型

  • 所有基本类型(int,float,boolean,byte,double,char,long,short)

  • String

  • Class

  • enum

  • Annotation

  • 上述类型的数组

通过代码进一步加深理解

package com.zach.annotation;

public @interface AnnotationDemo {
    
    //String 
    String value() default "";
    
    //boolean
    boolean flag() default false;
    
    
    //声明枚举类型
    Enum status() default Enum.FIXED;
    
    //Class类型
    Class<?> myClass() default Void.class;
    
    //嵌套注解
    AnnotationReference reference() default @AnnotationReference(next = true);
}

//枚举
enum Enum {FIXED,NORMAL};


//注解
@Target({ElementType.ANNOTATION_TYPE,ElementType.FIELD,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface AnnotationReference {
    boolean next() default false;
}

注意: 编译器对元素的默认值是有严格的限制的

  • 元素不能有不确定的值,要么具有默认值,要么在使用时提供元素的值
  • 对于非基本数据类型元素,无论是在源代码中声明,还是在注解接口中定义默认值,都不能以null作为值
  • 注解不支持继承,不能使用extends来继承某个@interface,但是注解在编译之后会自动继承java.lang.annotation.Annotation接口

故我们可以在设置默认值,以空字符串或负数来表示某个元素不存在

3. 参考资料  

深入理解Java注解类型(@Annotation)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值