深入理解Java自定义注解

分享知识 传递快乐


1. 基本语法

注解在Java中与类、接口、枚举类似,使用 @interface 关键字修饰类的类型。

public @interface Example {

    String value() default "";

}

使用 @interface 自定义注解时,自动继承了 java.lang.annotation.Annotation 接口。注解时不能继承其他的注解或接口。@interface 用来声明的方法名称就是参数的名称,返回值类型就是参数的类型(返回值类型只能是基本类型、Class、String、enum)。可以通过 default 来声明参数的默认值。

定义注解格式:

public @interface 注解名 {定义体}

注解参数的可支持数据类型:

  • 基本类型(int,float,boolean,byte,double,char,long,short)
  • String类型
  • Class类型
  • enum类型
  • Annotation类型
  • 以上所有类型的数组

定义注解类型元素时需要注意如下几点:

  • 访问修饰符必须为public,不写默认为public;
  • 该元素的类型只能是基本数据类型、String、Class、枚举类型、注解类型(体现了注解的嵌套效果)以及上述类型的一位数组;
  • 该元素的名称一般定义为名词,如果注解中只有一个元素,请把名字起为value(后面使用会带来便利操作);
  • ()不是定义方法参数的地方,也不能在括号中定义任何参数,仅仅只是一个特殊的语法;
  • default代表默认值,值必须和第2点定义的类型一致;
  • 如果没有默认值,代表后续使用注解时必须给该类型元素赋值。
     

2. 元注解:

元注解的作用就是负责注解其他注解。

  • @Target
  • @Retention
  • @Documented
  • @Inherited

这些类型和它们所支持的类在 java.lang.annotation 包中可以找到。

 

2.1 @Target

@Target 注解是专门用来限定某个自定义注解能够被应用在哪些Java元素上面使用。

@Target 修饰范围:可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了 target 可更加明晰其修饰的目标。

@Target 作用:用于描述注解的使用范围。

@Target 使用的一个枚举类型:

public enum ElementType {
    /** 用于描述类,接口(包括注解类型)或枚举的声明 */
    TYPE,

    /** 属性的声明 */
    FIELD,

    /** 方法的声明 */
    METHOD,

    /** 方法形式参数声明 */
    PARAMETER,

    /** 构造方法的声明 */
    CONSTRUCTOR,

    /** 局部变量声明 */
    LOCAL_VARIABLE,

    /** 注解类型声明 */
    ANNOTATION_TYPE,

    /** 包的声明 */
    PACKAGE
}

示例:

// 可以用于注解类、接口(包括注解类型) 或enum声明
@Target(ElementType.TYPE)
public @interface Example1 {

}

// 仅可用于注解类的成员变量
@Target(ElementType.FIELD)
public @interface Example2 {

}

// 可以用于注解参数、方法
@Target({ ElementType.PARAMETER, ElementType.METHOD })
public @interface Example3 {

}

 

2.2 @Retention

@Retention 定义了该 Annotation 被保留的时间长短,用来修饰自定义注解的生命力。

作用:用于描述注解的生命周期或被描述的注解在什么范围内有效

注解的生命周期有三个阶段:

  • Java源文件阶段;
  • 编译到class文件阶段;
  • 运行期阶段。

@Retention 注解使用了 RetentionPolicy 枚举类型定义了三个阶段:

public enum RetentionPolicy {

    // 在源文件中有效
    SOURCE,

    // 在class文件中有效
    CLASS,

    // 在运行时有效
    RUNTIME

}

说明

  • RetentionPolicy.SOURCE:这个注解它将被限定在Java源文件中,那么这个注解即不会参与编译也不会在运行期起任何作用,这个注解就和一个注释是一样的效果,只能被阅读Java文件的人看到;
  • RetentionPolicy.CLASS:这个注解它将被编译到Class文件中,那么编译器可以在编译时根据注解做一些处理动作,但是运行时JVM(Java虚拟机)会忽略它,我们在运行期也不能读取到;在默认的情况下,自定义注解是使用的 RetentionPolicy.CLASS。
  • RetentionPolicy.RUNTIME:这个注解可以在运行期的加载阶段被加载到Class对象中。那么在程序运行阶段,我们可以通过反射得到这个注解,并通过判断是否有这个注解或这个注解中属性的值,从而执行不同的程序代码段。我们实际开发中的自定义注解几乎都是使用的RetentionPolicy.RUNTIME;

示例:

// RetentionPolicy.RUNTIME 处理器可以通过反射获取到该注解的属性值,可以做一些运行时的逻辑处理
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Example {

    public String name() default "";
    public String value() default "";
	
}

 

2.3 @Documented

@Documented注解,是被用来指定自定义注解是否能随着被定义的 java 文件生成到 JavaDoc 文档当中,Documented 是一个标记注解,没有成员。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Example {

    public String name() default "";
    public String value() default "";
	
}

 

2.4 @Inherited

@Inherited 注解是一个标记注解,用于指定某个自定义注解;如果写在了父类的声明部分,那么子类的声明部分也能自动拥有该注解。@Inherited 注解只对那些 @Target 被定义为 ElementType.TYPE 的自定义注解起作用。

@Inherited
public @interface Example {

    public String value();
	
    String name();
	
}

 

 

 

 

 

 

 

 

—————————
如有不足请留言指正
相互学习,共同进步

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

旷野历程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值