什么是annotation?简单的说,是一种注解形式。
可能最有用地方的就是用于框架,有时候有一些代码需要不断重复地用到,这个时候就可以写成样板代码,并使用annotation来替代。试想,一个annotation替代成百上千行代码,可见其重要性。还有时候,你需要进行一些检查,比如说到底是不是重写了父类的方法。这些事情都可以使用Annotation来做,在编译的时候帮我们捕获部分的编译错误。
它并不直接影响代码的语义,可以从源文件读取,从.class文件读取,或者在运行时以反射的方式被读取。
java自身提供几种annotation,比如@deprecated,
从java 1.5以来,就允许开发者定义,使用自己的annotation类型了。
1.声明
要声明一个annotation,和声明一个接口类似。接口声明使用"interface"关键字,而annotation的声明需要使用到“@interface”关键字,多了一个"@"。它的级别和class,interface是一样的,所以在定义的时候,修饰符的位置也是一样的,在public的后面。但是还有一种写法。假如定义了一个MyAnnotation的annotation,那么就是@MyAnnotation public class XXX{ }
比如
public @interface MyAnnotation{
int id();
String name();
String career();
}
Annotation的成员变量和类不一样,而是一个方法的声明,方法的返回值类型只能是基本类型,String,Class,enums,annotation和这些类型的数组。注意:如果有且仅有一个成员变量,那么应该命名为value。
2.四种meta-annotation
java本身提供了4个meta-annotation,Retention,Documented,Target,Inherited。举个例子
@Documented,如果你想让你的Annotation里面的信息出现在javadoc生成的文件的话,那么就在@interface上面一行添加一个@Documented
@Retention(RetentionPolicy.RUNTIME),指示该annotation要保留多久,如果不声明的话,默认为保留策略为RetentionPolicy.CLASS,只要类被加载了,一直都可以。但是使用了RUNTIME声明以后,JVM会在运行时保留此类型的annotation,使其能够在运行时通过反射被读取。
@Target(ElementType.METHOD)的意思是说,此类型的annotation只能用于修饰方法声明。如果换成ElementType.Field,那么就用来修饰成员变量。
3.Annotaion的分类
1) 内建annotation
3种,@Deprecated,@Override,@SuppressWarnings,这3种都是所谓的编译器使用的Annotation。
@Deprecated表明这个元素已经过时了,不能再被使用了,如果继续使用这样的方法,就会报出Warnings。
@Override表明这是在重写副类的元素
@SuppressWarnings表明如果有warnings的话,那么就压制住它不给出来,比如deprecated的元素,本身会给出warnings,但是用了@SuppressWarnings,warnings就不会出现了。其实每个warning都属于一个category,一共只有2种分类,"deprecation"和"unchecked",如果要使用@SuppressWarnings的话,举例应该是
@SuppressWarnings("deprecation")
@SuppressWarnings({ "unchecked", "deprecation" })
至于unchecked类型,大概是为了忽略掉容器没有使用泛型而生成的警告。
2)开发者自己定义的annotation
和上面的声明部分一样,按照那个方法进行创建。
3)使用第三方开发的annotation
比如使用Hibernate,利用annotation生成数据表映射配置文件。
4.Annotation的使用
很多时候,如果有些信息你需要多次使用到,但是都是一样的,比如注释。假如你每次在写一个类的开头都要写一个注释,说明一些信息,每次写肯定不是最佳的方法,最佳的当然是专门定义一个固定的格式,每次开始的时候给各个元素赋上值就行了,比如创建时间,创建人。
按照惯例,Annotation单独占一行,然后后面加括号,跟着元素的值
a.举例,假设有一个叫做ServiceName的Annotation,那么就该按照如下
@ServiceName("GetUser")
b.假设元素不止一个,按照官方的例子
@Author(
name="Ben",
date="3/27/2003"
)
class Myclass( ){ }
c.如果没有元素的话,那么就连括号都省略了,就像Override一样
5.高级使用
比较高级的用法就是写一个annotation processor,读取java代码,然后根据annotations进行一些操作,比如生成辅助性的代码,从而将程序员必须创建可预测的格式的模版程序中缓解出来。
从JDK1.5开始,有了这个功能,必须使用@Retention(RetentionPolicy.Runtime)
举个例子
@Retention(RetentionPolicy.Runtime)
@interface AnnotationForRuntime{
//Elements that give information
//for runtime processing
}
@Target
只有几个值,装在一个枚举类里面,叫做ElementType,有几个值,分别是
ElementType.TYPE
ElementType.METHOD
ElementType.FIELD
ElementType.CONSTRUCTOR
ElementType.PARAMETER
ElementType.LOCAL_VARIABLE
ElementType.ANNOTATION_TYPE
ElementType.PACKAGE
大家分别的意思就是说,这个Annotation只能用于Class,Method...的声明,如果你制定了ElementType的话,在真正使用的时候确实就必须遵循这个原则了。