Java Annotation原理分析(三) --- 内置Annotation介绍

6.   Java语言内置的Annotation简介

6.1  基本内置类型

     在Java 1.5 之后,引入了三个基本的Annotation类型,分别为: @Override,@Deprecated, @SuppressWarnings.

  1.    @Override

                 java.lang.Override,作用于方法级别,只存在与编译阶段使用,由于其定义涵盖@Target(value=METHOD), @Retention(value=SOURCE)。

         其为Marker Annotation, 仅用作标识方法,表示其重载了父类的方法;如果使用了@Override,实际上却并未覆盖父类方法,java编译器将提示一个编译错误。我们其实,可以将其理解为一个强化语法检查的断言,辅助开发者减少错误。

       2.     @Deprecated

     标识Annotation,作用于方法各个级别的代码,在运行阶段使用。

     在使用@Deprecated修饰的方法、变量等之后,编译器将不鼓励使用这个被标注的程序元素。使用这种修饰可以扩散到子类中,例如在代码中通过继承或者覆盖的方式使用了这个@Deprecated标识的类型或者成员,即使继承或者覆盖后的类型或者成员并不是被声明为 @Deprecated,但编译器仍然要抛出警告信息。  

    3. @SuppressWarnings

  在代码中,适用于所有代码级别,Retention适用于源代码级别(Source),用以提示Java编译器Java编译器关闭对类、方法及成员变量的警告。对于代码中不希望反复看到的警告信息,可以通过这个注解来屏蔽,编译器将不再抛出警告。

      与之前的两个Annotation不同,@SuppressWarnings可以使用响应的成员变量,从而可以更精细化的控制提示警告信息的出现。对于javac编译器来讲,被-Xlint选项有效的警告名也同样对@SuppressWarings有效,同时编译器忽略掉无法识别的警告名。

  其内部可以基于String[],传入需要屏蔽的警告类型信息。使用示例如下:

@SuppressWarnings(value={"unchecked","fallthrough"})
public void suppressedMethod() { 
   //Logic Code
}

 这里仅仅列出了两种需要屏蔽的警告类型,如需查看所有可能的警告信息类型,可以查看参考资料4.

6.2 Meta-Annotation

   主要功能是用以修饰Annotation,简而言之,就是用以创建新的Annotation的修饰Annotation。虽然有点绕口,Meta-Annotation就明确地表明他的位置。先看一个例子吧:

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
   ElementType[] value();
}
这个是Target在JDK源码中的定义,通过这个例子充分说明了Meta-Annotation的用法。 这里比较有意思的是,@Target在源码中是通过自我定义来完成的,就是@Target本身是使用@Target来修饰和定义的。

   这个例子中@Documented标识其会在javadoc中出现,@Retention标识其在代码运行中使用,@Target标识其仅用作Annotation类型。

   接下来,我们将分别对这些Meta-Annotation做详细讲解。

  1.    @Target

         限定Annotation所修饰的对象范围,范围包括packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标,一句话,这个Annotation可以用在什么地方。

  可用的取值(ElementType)有:

  • CONSTRUCTOR:用于描述构造器
  • FIELD:      用于描述域
  • LOCAL_VARIABLE:   用于描述局部变量
  • METHOD:用于描述方法
  • PACKAGE:用于描述包
  • PARAMETER:用于描述参数
  • TYPE:用于描述类、接口(包括注解类型) 或enum声明

     2. @Rentention

       定义了该Annotation被保留的时间长短,或者说生命周期,即其会在哪个阶段被保留,并在哪个阶段会被使用到。

       其value的取值(RetentionPoicy)有:

  •  SOURCE:在源文件中有效(即源文件保留)

              出现在源代码中,而被编译器丢弃。

  • CLASS:在class文件中有效(即class保留)

                 被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略。

  • RUNTIME:在运行时有效(即运行时保留)

               其被编译到class中,并在运行时,被读取和使用的。

     3.  @Documented

         描述其它类型的annotation被作为被标注的程序成员的公共API,从而被javadoc此类的工具文档化。标记注解,没有成员

     4.   @Inherited

         标记注解,标识某个被标注的类型是被继承的。使用了@Inherited修饰的annotation类型被用于一个class之时,,则这个annotation将被用于该class的相应子类。

  注意:@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。

  当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。

      就是说, 查看查找@Inherited过的Annotation之时,需要反复的向上查找,方才可以。

     下面以Spring中@Controller的定义为样例来看看它们的使用:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
}

    @Target中ElementType.Type标识其用于类或借口,Rention标识运行中,@Documented标识其已经在Javadoc中标识出来。 @Component是Spring中自定义的一个Annotation,标识其可以被IOC容器自动探测到。

     限于篇幅,这里就不再针对@Inherited做示例讲解了,大家如果感兴趣的话,可以查看以下链接中的示例,就一目了然了。

    范例讲解:  http://www.jroller.com/alessiopace/entry/annotation_inheritance_examples

总结: 在本节中,我们着重讲解了Java语言中内置的Annotation和Meta-Annotation。


你可能感兴趣的:(Java技术)