您的位置:首页 > 编程语言 > Java开发

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

2014-01-25 14:23 381 查看
6. Java语言内置的Annotation简介

6.1 基本内置类型

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

@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做详细讲解。

@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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: