Java自定义注解相关学习

Annotation
简介
​ Annotation(注解)是JDK5开始引入的新特性,可以看作是一种特殊的注释,主要用于修饰类,方法或者变量,在框架中大量使用(如 Spring、Mybatis等)

注解是一种能被添加到java代码中的元数据,类、方法、变量、参数和包都可以用注解来修饰。注解对于它所修饰的代码并没有直接的影响。

​ 下面是简单的一个自定义注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Test {
    public int id() default -1;

    public String msg() default "Hi";
}


​ 通过对上述文件的字节码(.class)的反编译(javap - p xxx.class)可以得到@interface其实就是一个继承了Annotation的一个接口

javap -p Test.class
public interface com.dyw.annotation.Test extends java.lang.annotation.Annotation {
  public abstract int id();
  public abstract java.lang.String msg();
}

​ 注解只有被解析之后才会生效,常见的解析方法有两种:

编译期间直接扫描:编译器在编译Java代码的时候扫描对于的注解并处理,比如某个方法使用了@Override,编译器在编译的时候就会检测当前的方法是否重写了父类对于的方法。
运行期间通过反射处理:这个经常在Spring框架中看到,例如Spring的@Value注解,就是通过反射来进行处理的。

注解详细介绍
我们通过上述的例子可以看到我们的注解上面还有着其他的注解例如@Retention、@Target(这些都统称为元注解),所以一个注解是由以下成分组成

元注解
public @interface 注解名称
元注解介绍
​ JDK1.8版本为我们提供了6个标准的用来对注解类型进行注解的注解类(1.8之前只有四个),我们称之为meta-annotation(元注解)

​ 元注解只能用在注解之上(自定义注解时可用)

@Target

@Retention

@Documented

@Inherited

@Native(1.8新增)

@Repeatable(1.8新增)

@Target

  • 它指明了它所修饰的注解使用的范围 如果自定义的注解为含有@Target元注解修饰,那么默认可以是在(除类型参数之外的)任何项之上使用,若有@Target元注解修饰那么根据Value(ElementType枚举常量)的指定的目标进行规定。
public enum ElementType {
    /** 类、接口(包括注解类型)或枚举声明 */
    TYPE,

    /** 字段声明(包括枚举常量) */
    FIELD,

    /** 方法声明 */
    METHOD,

    /** 参数声明 */
    PARAMETER,

    /** 构造函数声明 */
    CONSTRUCTOR,

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

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

    /** 包装声明 */
    PACKAGE,

    /**
     * 类型参数声明 类型参数即Map<String,Integer>中的String和Integer这里是作为类型
     *
     * @since 1.8
     */
    TYPE_PARAMETER,

    /**
     * 使用类型 对应于 JLS 4.11 中的 15 个类型上下文,以及两个声明上下文:类型声明(包括注解类型声明)和类型参数声明。
     *
     * @since 1.8
     */
    TYPE_USE
}

ElementType的枚举常量指明了注解可以使用的目标。
@Target(ElementType.METHOD)//可修饰在方法之上

@Retention

  • @Retention用来约束注解的生命周期,分别有三个值,源码级别(source)、类文件级别(class)或者运行时级别(runtime)可以通过指定@Retention中的值来实现(值为RetentionPolicy枚举常量)。
  • ​ 注意:生命周期大小排序为SOURCE < CLASS < RUNTIME,范围依次增大,前者能使用的地方后者一定能使用。如果需要在运行时去动态获取注解信息,那只能使用RUNTIME;如果要在编译时进行一些预处理操作,比如生成一些辅助代码,就是用CLASS;如果只是做一些检查性的操作,比如@Override和@SupperssWarning,可选择SOURCE
     

@Documented

  • 带上该注解后的注解表明,在默认情况下这个注解是由JavaDoc和类似工具记录的,即带上了该文档化的注解被使用再生成文档时,会称为API的一部分。(默认情况下JavaDoc是不包含注解的,除非声明注解的时候使用了@Documented
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Person {
    String name() default "";
}
public class main {
    @Person(name = "ding")
    public static void main(String[] args) {

        System.out.println("hello");
    }
    //@Person(name = "ding")
    @Person(name = "yang")
    public static void doSome(){

    }
}

生成的文档:

  • 不带@Documented注解生成的文档

@Inherited

  • 被该元注解修饰的自定义注解再使用后会自动继承,如果使用了该自定义注解去修饰一个class那么这个注解也会作用于该class的子类。就是说如果某个类使用了被@Inherited修饰的注解,则其子类将会自动具有该注释
  • ​ 注意: @Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation
@Inherited //使用@Inherited修饰的自定义注解
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Person {
    String name() default "";
}
public class main {
    public static void main(String[] args) {
        System.out.println(Father.class.getAnnotation(Person.class));
        System.out.println(Son.class.getAnnotation(Person.class));
    }

}

@Person
class Father {
}
class Son extends com.dyw.annotation.obj.Father {

}


@Native

  • 使用 @Native 注解修饰成员变量,则表示这个变量可以被本地代码引用,常常被代码生成工具使用。对于 @Native 注解不常使用,了解即可。


@Repeatable

@Repeatable允许在相同的程序元素中重复注解(不报错)。在需要对同一种注解多次使用时,往往需要借助 @Repeatable 注解。Java 8 版本以前,同一个程序元素前最多只能有一个相同类型的注解,如果需要在同一个元素前使用多个相同类型的注解,则必须使用注解“容器”。

不使用@Repeatable修饰的自定义注解完成重复注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Persons {
    Person[] value();
}

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Person {
    String name() default "";
}

@Persons(value = {@Person(name = "ding"),@Person(name = "yang")})
public static void doSome(){

}

​ 使用@Repeatable修饰的自定义注解

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Persons {
    Person[] value();
}

@Repeatable(Persons.class)
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Person {
    String name() default "";
}
@Person(name = "ding")
@Person(name = "yang")
public static void doSome(){

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值