Annotation注解类

Annotation注解类

本文结构:

Annotation.png

1. 概念

Java Annotation是JDK5.0引入的一种注释机制。

关于Annotation注解的概念,我们可以先看下官方的解释:

Annotations, a form of metadata;
provide data about a program that is not part of the program itself.
Annotations have no direct effect on the operation of the code they annotate

Annotation注解是Java中的一种元数据,它可以往程序中添加额外的数据,并且对注解的代码无直接的影响。注解是一种接口,可以作用于包名、类、方法、属性、参数等。它可以通过反射机制来访问annotation信息,获得所加的注解信息。

2. Java.lang中的注解

Java.lang中的注解又称为标准Annotation,即常用到的Deprecated、Override和SuppressWarnings。
(1)@Deprecated 过时:表示该方法已过时,建议使用新的一些方法代替。
(2)@Override 复写:表示复写父类的方法,如果方法上有这条注解但没有重写父类方法,则会生成一条错误信息。这个注解保证了方法一定会被复写。比如在开发过程中,手动在子类中复写父类的方法,只正确写出了方法名称,未写出正确的方法参数,则相当于方法的重载,并不是复写。所以使用@Override注解,有效地表明,此方法是复写父类的方法,不会产生手动的错误问题。
(3)@SuppressWarnings 阻止警告,阻止弹出的警告,比如加上此注解可屏蔽上述过时的警告。

3. 元注解

元注解是指注解Annotation的注解。以Override的源代码为例:

1
2
3
4
@Target(ElementType.METHOD)  
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

注解类的定义方法以及注解类上所加的注解。元注解有四个,位于java.lang.annotation包中:Target,Retention,Documented、Inherited。

3.1 @Target 表示注解作用的目标。

1
2
3
4
5
6
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target{
ElementType[] value();
}

注解作用的目标由枚举类ElementType决定。

1
2
3
4
5
6
7
8
9
10
public enum ElementType{
TYPE,//类、接口、注解类型或枚举
FIELD,//属性
METHOD,//方法
PARAMETER,//用于描述参数
CONSTRUCTOR,//构造方法
LOCAL_VARIABLE,//局部变量
ANNOTATION_TYPE,//注解类
PACKAGE,//包
}

:Class,interface等都实现了java中的Type接口,因此ElementType.TYPE表示注解作用于这些“类”(并不是单纯的Class类)

3.2 @Retention 表示注解的作用时段

1
2
3
4
5
6
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target{
RetentionPolicy value();
}

由源码可见,Retention定义的是RetentionPolicy类型的数据

1
2
3
4
5
public enum RetentionPolicy{
SOURCE,//表示注解只在源文件中保留
CLASS,//表示注解保留到.class文件中
RUNTIME,//表示注解一直保留到内存中,类加载器把.class文件加载到内存中产生的字节码中要保留注解信息
}

3.3 @Documented 表示javadoc所生成的文档会带上注解信息。
3.4 @Inherited 表示子类可以集成加载父类上的注解,但要注意:(1)注解定义在类上面,子类可以继承该注解;(2)注解定义在方法上,子类也可继承该注解;但是如果子类复写了父类中定义了注解的方法,子类将无法继承该方法上的注解;(3)Interface的实现类无法继承接口中所定义的被@Inherited标注的注解

4. 注解的参数

参数类型支持基本数据类型、Class类型、enum类型、Annotation类型以及上述所有类型的数组。

5. 自定义注解

步骤:

  1. 使用@interface定义一个注解类(其内部自行继承了Annotation类)
  2. 在该类中定义注解的参数(类似定义方法)
  3. 注解元素必须由确定的值,可在定义注解的默认值中指定,也可在使用注解时指定(非基本类型的注解元素的值不可为null)
    example:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    @Documented
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface Car{
    String name() default "";
    int number() default -1;
    }

    @Car(name = "宝马", number = 666)
    public class CarBWM{
    public static void main(String[] args){
    //判断CarBMW是否有注解类Car
    if(CarBMW.class.isAnnotationPresent(Car.class)){
    Car carAnnotation = (Car)CarBMW.class.getAnnotation(Car.class);
    System.out.println("car name " + carAnnotation.name());
    System.out.println("car number " + carAnnotation.number());
    }
    }
    }