Java 注解从JDK1.5开始引入,用于为 Java 代码提供元数据(标签)。作为元数据,注解不直接影响目标代码执行,但也有一些类型的注解也可以用于这一目的。注解可以简化配置、提高编码效率,目前大部分主流开发框架(Spring、Mybatis)都使用了注解。
定义注解
注解使用 @interface 关键字进行定义,@interface 同 classs 和 interface 一样属于一种类型。它的形式跟接口类似,不过前面多了一个 @ 符号。下面示例创建了一个名字为 AnnotationTest的注解。
public @interface AnnotationTest{
}
使用注解
在需要注解的地方使用 @AnnotationTest就可以了。下面示例使用AnnotationTest注解Test类。
@AnnotationTest
public class Test {
}
元注解
元注解是注解的注解,元注解是一种特殊的注解,它的作用是为其他普通注解进行解释说明。元注解包括@Retention、@Documented、@Target、@Inherited、@Repeatable 5 种,其中@Repeatable 是Java8中引入的注解。
@Retention
@Retention用于定义注解的保留策略(生命周期),它解释说明了这个注解的的存活时间。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
*/
RetentionPolicy value();
}
注解的保留策略包含RetentionPolicy.SOURCE、RetentionPolicy.CLASS、RetentionPolicy.RUNTIME三种,其中SOURCE < CLASS < RUNTIME。
public enum RetentionPolicy {
/**
* 注解仅存在于源码中,编译时它将被丢弃,在class字节码文件中不包含;
* 一般用于做一些检查性的操作,比如 @Override 和 @SuppressWarnings。
*/
SOURCE,
/**
* 默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得;
* 一般用于在编译时期进行一些预处理操作,比如生成一些辅助代码。
*/
CLASS,
/**
* 注解会在class字节码文件中存在,在运行时可以通过反射获得;
* 一般用于在运行时去动态获取注解信息。
* @see java.lang.reflect.AnnotatedElement
*/
RUNTIME
}
@Documented
@Documented说明该注解将被包含在javadoc中去。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
@Target
@Target定义注解的作用目标(如方法、类、字段等),限定了注解的作用场景,其中ElementType是枚举类型。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
*/
ElementType[] value();
}
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
}
当注解未指定Target值时,则此注解可以用于任何元素之上,多个值使用{}包含并用逗号隔开,如下
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
@Inherited
@Inherited说明被注解的类的子类可以继承父类中的该注解,并不是说注解本身可以继承。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
下面示例中,注解 AnnotationTest 被 @Inherited 修饰,之后类 A 被 AnnotationTest 注解,类 B 继承 A,类 B 也拥有 AnnotationTest 这个注解。
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface AnnotationTest {}
@AnnotationTest
public class A {}
public class B extends A {}
@Repeatable
@Repeatable是Java 8 引入的新特性,表示在同一个位置可以重复使用相同的注解。
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Repeatable {
/**
* Indicates the <em>containing annotation type</em> for the
* repeatable annotation type.
* @return the containing annotation type
*/
Class<? extends Annotation> value();
}
下面示例中定义一个人既是产品经理又是研发工程师也是测试工程师
/**
* Persons 相当于一个容器注解,
* 按照规定,它里面必须要有一个 value 的属性,属性类型是一个被 @Repeatable 注解过的注解数组。
* 这里可以理解为 Persons 是一张总的标签,上面贴满了 Person 这种同类型但内容不一样的标签。
*/
@interface Persons {
Person[] value();
}
/**
* @Repeatable 后面括号中指定容器注解
*/
@Repeatable(Persons.class)
@interface Person{
String role default "";
}
@Person(role="PM")
@Person(role="RD")
@Person(role="QA")
public class SuperMan{}
注解属性
获取注解
注解的使用场景
Java内置注解
Spring中的注解
参考文献:
https://blog.csdn.net/javazejian/article/details/71860633#%E7%90%86%E8%A7%A3java%E6%B3%A8%E8%A7%A3
https://blog.csdn.net/briblue/article/details/73824058
https://www.jianshu.com/p/b560b30726d4
https://blog.csdn.net/yerenyuan_pku/article/details/52583656
http://baijiahao.baidu.com/s?id=1586102004406399575&wfr=spider&for=pc
https://www.cnblogs.com/lyy-2016/p/6288535.html