Java 注解的玩儿法。

本贴最后更新于 2066 天前,其中的信息可能已经物是人非

元注解是指注解的注解,包括 @Retention @Target @Document @Inherited 四种。

呃,看了一眼源码其实 8(我截止到今天用的是 8,2018/8/1)里面还有 @Repeatable。
WX201808011513532xpng

先按顺序来分析:

1、@Retention 作用

定义注解的保留策略

  • @Retention(RetentionPolicy.SOURCE): 注解仅保存在源码阶段,编译和运行时都不会有。
/**
 * Annotations are to be discarded by the compiler. 
 */
 SOURCE,
  • @Retention(RetentionPolicy.CLASS): 注解会在 class 字节码中存在,运行时不可见。此策略为默认。
/**
 * Annotations are to be recorded in the class file by the compiler 
 * but need not be retained by the VM at run time.  This is the default 
 * behavior. 
 */
 CLASS,
  • @Retention(RetentionPolicy.RUNTIME): 注解会在 class 字节码文件中存在,在运行时可以通过反射获取到
/**
 * Annotations are to be recorded in the class file by the compiler and 
 * retained by the VM at run time, so they may be read reflectively. 
 * 
 * @see java.lang.reflect.AnnotatedElement
 */
 RUNTIME

2、@Target: 定义注解的作用目标

public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
  TYPE,  // 类,接口,枚举,注解。

    /** Field declaration (includes enum constants) */
  FIELD, // 字段, 枚举常量。

    /** Method declaration */
  METHOD, // 方法

    /** Formal parameter declaration */
  PARAMETER, // 方法参数

    /** Constructor declaration */
  CONSTRUCTOR, // 构造函数

    /** Local variable declaration */
  LOCAL_VARIABLE, // 局部变量

    /** Annotation type declaration */
  ANNOTATION_TYPE, // 注解

    /** Package declaration */
  PACKAGE, // 包

    /**
	 * Type parameter declaration 
	 * 
	 * @since 1.8
	 */  
 TYPE_PARAMETER, // 新特性,表示这个 Annotation 可以用在 Type 的声明式前

    /**
	 * Use of a type * * @since 1.8
	 */  
 TYPE_USE // 新特性,表示当前Annotation 可以用在所有使用 Type 的地方(如:泛型,类型转换等)。
}

3、@Documented

表示可以出现在 javadoc 中,

4、@Inherited

该注解表示子类可以集成加载父类上的注解。但要注意:

 1.注解定义在类上面,子类是可以继承该注解的。

 2.注解定义在方法上面,子类也可以继承该注解,但是如果子类复写了父类中定义了注解的方法,那么子类将无法继承该方法的注解,也就是说,子类在复写父类中被@Inherited标注的方法时,会将该方法上面的注解覆盖掉

 3.Interface的实现类(implements实现)无法继承接口中所定义的被@Inherited标注的注解

@Inherited 的总结来自:
CShawnX:Java 和 Android 中的注解

5、@Repeatable 可以重复注解

在之前,相同的注解在同一个位置只能使用一次, java8 引入了重复注解机制。可以让一个注解在一个位置引用多次。例如:

@interface Persons { 
    Person[] value(); 
}

@Repeatable(Persons.class)
@interface Person{ 
    String role default""; 
}

@Person(role="artist")
@Person(role="coder")
@Person(role="PM")
public class SuperMan{ 

}

表示这个 SuperMan 可以是三种角色,artist,coder,PM。

上面代码中,用 @Repeatable 注解了注解 Person,而其括号内的 Persons.class 表示为一个注解容器。
按照规定,它里面必须要有一个 value 的属性,属性类型是一个被 @Repeatable 注解过的注解数组,注意它是数组。

注解怎么玩儿?

注解是一系列元数据,它提供数据用来解释程序代码,但是注解并非是所解释的代码本身的一部分。注解对于代码的运行效果没有直接影响。

注解有许多用处,主要如下:

  • 提供信息给编译器: 编译器可以利用注解来探测错误和警告信息
  • 编译阶段时的处理: 软件工具可以用来利用注解信息来生成代码、Html 文档或者做其它相应处理。
  • 运行时的处理: 某些注解可以在程序运行的时候接受代码的提取

玩儿法一

java 预置了一些注解,可以通过这些注解,对代码进行描述。达到某种目的。
@Deprecated、@Override、@SuppressWarnings、@SafeVarargs、@FunctionalInterface

玩儿法二

那就是自己定义一些注解了。
通过反射,获得相关的注解,并未目标增加一系列附加的处理操作。因为正像官方描述:注解对于代码的运行效果没有直接影响。但是我们可以为其增强啊。
getAnnotation()或者 getAnnotations()可以获得目标的注解对象或者所有注解的数组。再根据这些注解对象以及其成员属性。
可以据此为其编写外部能力。

应用场景

日志、测试类、Ioc、功能增强等。

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1090 引用 • 3467 回帖 • 298 关注
  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3165 引用 • 8206 回帖
  • 反射
    18 引用 • 29 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • JFLB0907

    都是大神😂

  • wenandlu

    以前玩过,根据实体类注解,生成列表的 excel 导出文件,还是比较实用的,也不会破坏代码结构,所以提醒一下,有个 RUNTIME 注解很重要,我曾在这里耗费过半天时间,就是没有加入 RUNTIME 注解,导致获取不到注解