注解简单分析
一、定义
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
二、作用分类
编写文档:通过代码里标识的注解生成文档 (生成文档doc文档)
代码分析:通过代码里标识的注解对代码进行分析 (使用反射)
编译检查:通过代码里标识的注解让编译器能够实现基本的编译检查 (Override)
三、注解分类
3.1 元注解
元注解是由java API提供的,是专门用来定义注解的注解,常用的元注解主要包括Documented、Inherited、Retention、Target四个,其作用分别如下:
(1) Documented:
源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
表示拥有该注解的元素可通过javadoc此类的工具进行文档化。注解只是一个标记的话,那么使用javadoc生成文档时,这些注解都不会存在于文档中,要使注解在文档中也存在,就可以在使用了注解的作用对象上加上@Documented这个注解。javadoc所生成的文档就会带上注解信息。
(2) Inherited:
源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}
该注解表示子类可以集成加载父类上的注解。但要注意:
注解定义在类上面,子类是可以继承该注解
注解定义在方法上面,子类也可以继承该注解,但是如果子类复写了父类中定义了注解的方法,那么子类将无法继承该方法的注解,也就是说,子类在复写父类中被@Inherited标注的方法时,会将该方法上面的注解覆盖掉
Interface的实现类(implements实现)无法继承接口中所定义的被@Inherited标注的注解
(3) Retention:
源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
表示该注解类型的注解保留的时长。当注解类型声明中没有@Retention元注解,则默认保留策略为RetentionPolicy.CLASS。关于保留策略(RetentionPolicy)是枚举类型,共定义3种保留策略,如下表:
RetentionPolicy | 含义 |
---|---|
SOURCE | 仅存在Java源文件,经过编译器后便丢弃相应的注解 |
CLASS | 存在Java源文件,以及经编译器后生成的Class字节码文件,但在运行时VM不再保留注释 |
RUNTIME | 存在源文件、编译生成的Class字节码文件,以及保留在运行时VM中,可通过反射性地读取注解 |
(4) Target:
源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
}
表示该注解类型的所使用的程序元素类型。当注解类型声明中没有@Target元注解,则默认为可适用所有的程序元素。如果存在指定的@Target元注解,则编译器强制实施相应的使用限制。关于程序元素(ElementType)是枚举类型,共定义8种程序元素,如下表:
ElementType | 含义 |
---|---|
ANNOTATION_TYPE | 注解类型声明 |
CONSTRUCTOR | 构造方法声明 |
FIELD | 字段声明(包括枚举常量) |
LOCAL_VARIABLE | 局部变量声明 |
METHOD | 方法声明 |
PACKAGE | 包声明 |
PARAMETER | 参数声明 |
TYPE | 类、接口(包括注解类型)或枚举声明 |
3.2 内建注解
在内建注解中,常用到三种注解类,即常用到的Deprecated、Override和SuppressWarnings.
(1) Deprecated:
源码:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
用途:用于告知编译器,某一程序元素(比如方法,成员变量)不建议使用时,应该使用这个注解。Java在javadoc中推荐使用该注解,一般应该提供为什么该方法不推荐使用以及相应替代方法。
注解类型分析: @Deprecated可适合用于除注解类型声明之外的所有元素,保留时长为运行时VM。
在使用Eclipse或AS编写程序过程中,有一些方法编写出来之后被画上了中划线,表示该方法已过时,建议使用新的一些方法代替。如:viewPager.setOnPageChangeListener()方法在安卓API23中已过时,在上面被画上了中划线,在源代码中的该方法上赫然多了一个注解@Deprecated,可使用addOnPageChangeListener()方法代替。如果使用javac命令编译,会弹出:”注意:使用或覆盖了已过时的API“。
(2) Override:
源码:
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
用途:用于告知编译器,我们需要覆写父类的当前方法。这是开发过程中最常遇到的注解了,表示复写父类中的方法。如果方法上有这条注解但没有重写父类方法,则会生成一条错误消息。这个注解有效地保证了方法一定会被复写。比如开发过程中,手动在子类中复写父类方法,只正确写出了方法名称,未写正确方法的参数,则相当于方法的重载,并不是复写。这种问题如果在功能上有错误产生,在检查过程中是很难找到的。使用@Override注解,有效地表明,此方法是复写父类的方法,不会产生手动的错误问题。
注解类型分析:@Override可适用元素为方法,仅仅保留在java源文件中。
(3) SuppressWarnings:
源码:
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
String[] value();
}
用于ÿ