java语言:注解


通过注解,我们可以为源代码添加元数据信息,包括编译或部署信息、配置属性、编译行为或者代码质量检查。

与Javadoc不同,注解属于强类型,用到的注解在类路径下都能找到对应的注解类型定义。因此,定义的注解可以在运行时访问到,而Javadoc是不可能的。

注解语法

注解通常出现在被注解的代码段前面,通常情况下都是独立成行并且与代码段同样缩进。

注解可以添加到package(包)、types(类型,包括类、接口、枚举和其它注解类型)、variable(变量、包括class、类实例、局部变量——包括定义在for或者while循环里面的局部变量)、constructions(构造方法)、methods(方法)和parameters(参数)。

最简单的注解结构就是内部什么元素都没有,例如:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>()
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">theMethod</span>() {…}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

在这个例子中,括号可以省略(因为没有参数):

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Override</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">void</span> <span class="hljs-title" style="box-sizing: border-box;">theMethod</span>() {…}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li></ul>

注解也可以包含元素,这些元素是通过逗号分隔的键值对。允许使用的值类型包括java原生数据类型、String类型、枚举类型,以及这些类型的数组形式:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Author</span>(name = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Albert"</span>,
        created = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"17/09/2010"</span>,
        revision = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">3</span>,
        reviewers = {<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"George"</span>, <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Fred"</span>})
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">SimpleAnnotationsTest</span> {</span>…}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li></ul>

当注解内部只有一个元素,并且这个元素名为value的时候,元素名可以省略:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@WorkProduct</span>(<span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"WP00000182"</span>)
<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Complexity</span>(ComplexityLevel.VERY_SIMPLE)
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">SimpleAnnotationsTest</span> {</span>…}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li></ul>

注解可以为内部一些元素或者全部元素都设置默认值。在使用这类注解的时候,具备默认值的元素可以省略。

例如,假设有个注解为Author,它为内部元素revision(默认为1)以及reviewers(默认为空String数组)设置了默认值,下面使用这个注解的两种方式是等效的:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Author</span>(name = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Albert"</span>,
        created = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"17/09/2010"</span>,
        revision = <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>,
        reviewers = {})
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">SimpleAnnotationsTest</span>() {</span>…}
<span class="hljs-annotation" style="color: rgb(155, 133, 157); box-sizing: border-box;">@Author</span>(name = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"Albert"</span>,        <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// defaults are revision 1</span>
        created = <span class="hljs-string" style="color: rgb(0, 136, 0); box-sizing: border-box;">"17/09/2010"</span>) <span class="hljs-comment" style="color: rgb(136, 0, 0); box-sizing: border-box;">// and no reviewers</span>
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">class</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">SimpleAnnotationsTest</span>() {</span>…}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li></ul>

注解的典型使用

Java语言规范中定义了三种注解类型——它们都用于Java编译器:

  • @Deprecated: 用来声明被注解的元素不应该再使用。每当这个注解被使用的时候,编译器就会生成一个警告。它应该与Javadoc的@deprecated一起使用,在Javadoc中解释舍弃被注解元素的原因。

  • @Override: 用来声明被注解的元素重写了父类中声明的元素。如果被注解的元素没有在父类中找到对应的被重写的元素,编译器就会生成一个警告。尽管这个注解没有要求一定要使用,但是它对于错误判断非常有用——例如,如果在创建父类之后,有人又修改了父类方法的签名,那么我们在重新编译源代码的时候就能马上得到提醒。

  • @SuppressWarnings: 让编译器抑制指定的警告类型,否则被注解的元素就会触发这类警告——例如,为了避免使用了被舍弃的API或者与旧代码(例如Java 5之前的版本)进行了未检查的交互而产生过多的编译器“干扰”。

自从引入这些注解后,很多库和框架都将注解集成到它们新的发行版本中。通过在源代码中使用注解,这些库和框架都简化甚至移除了所需要的配置文件。

下面是一些成功使用注解的例子:

  • Java企业版和它的主要模块——企业级JavaBeans、Java持久化API或者Web Service API。
  • Spring框架——用于核心模块中的配置、依赖注解和控制反转中,以及其它一些Spring项目。
  • Sean、Weld、Guice.
  • Apache Struts 2.

注解类型

在Java语言中注解类型是一种特殊的接口,用来自定义注解。

注解的定义要使用@interface关键字来代替interface

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> @<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Author</span> {</span>
    String name();
    String created();
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">int</span> revision() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">default</span> <span class="hljs-number" style="color: rgb(0, 102, 102); box-sizing: border-box;">1</span>;
    String[] reviewers() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">default</span> {};
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> @<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Complexity</span> {</span>
    ComplexityLevel value() <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">default</span> ComplexityLevel.MEDIUM;
}
<span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">enum</span> ComplexityLevel {
    VERY_SIMPLE, SIMPLE, MEDIUM, COMPLEX, VERY_COMPLEX;
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li><li style="box-sizing: border-box; padding: 0px 5px;">7</li><li style="box-sizing: border-box; padding: 0px 5px;">8</li><li style="box-sizing: border-box; padding: 0px 5px;">9</li><li style="box-sizing: border-box; padding: 0px 5px;">10</li><li style="box-sizing: border-box; padding: 0px 5px;">11</li><li style="box-sizing: border-box; padding: 0px 5px;">12</li></ul>

注解类型与普通的接口有一些区别:

  • 只允许原生数据类型、String、枚举、class,以及这些类型的数组。注意注解类型中不允许常用的对象,也不允许数组的数组(因为每一个数组都是一个对象)。

  • 注解元素的定义与定义方法的语法很类似,但是不允许有修饰符和参数。

  • 注解元素的默认值定义需要使用default关键字,后面连接字面量、初始化数组或者枚举值。

正如其它的类或者接口,枚举类型也可以嵌套在注解类型的内部:

<code class="language-java hljs  has-numbering" style="display: block; padding: 0px; background-color: transparent; color: inherit; box-sizing: border-box; font-family: 'Source Code Pro', monospace;font-size:undefined; white-space: pre; border-top-left-radius: 0px; border-top-right-radius: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; word-wrap: normal; background-position: initial initial; background-repeat: initial initial;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> @<span class="hljs-class" style="box-sizing: border-box;"><span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">interface</span> <span class="hljs-title" style="box-sizing: border-box; color: rgb(102, 0, 102);">Complexity</span> {</span>
    <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">public</span> <span class="hljs-keyword" style="color: rgb(0, 0, 136); box-sizing: border-box;">enum</span> Level {
        VERY_SIMPLE, SIMPLE, MEDIUM, COMPLEX, VERY_COMPLEX;
    }
    …
}</code><ul class="pre-numbering" style="box-sizing: border-box; position: absolute; width: 50px; background-color: rgb(238, 238, 238); top: 0px; left: 0px; margin: 0px; padding: 6px 0px 40px; border-right-width: 1px; border-right-style: solid; border-right-color: rgb(221, 221, 221); list-style: none; text-align: right;"><li style="box-sizing: border-box; padding: 0px 5px;">1</li><li style="box-sizing: border-box; padding: 0px 5px;">2</li><li style="box-sizing: border-box; padding: 0px 5px;">3</li><li style="box-sizing: border-box; padding: 0px 5px;">4</li><li style="box-sizing: border-box; padding: 0px 5px;">5</li><li style="box-sizing: border-box; padding: 0px 5px;">6</li></ul>

用于定义注解的注解

JDK自带了一些注解,用于修改我们自定义的注解的默认行为。

  • @Documented: 声明被@Documented注解后的注解类型,一旦使用,被注解的元素就应该连同注解都记录到Javadoc中。

  • @Inherited: 声明被注解的注解类型能够继承到它的子类上。通过这种方法,如果当前子类没有受@Inherited注解的注解类型注解过,但是它的父类有,那么当前子类也能通过继承得到这个注解类型。不过它只适用于类继承,不适用于接口实现。

  • @Retention: 声明被注解的注解类型生命周期。可选的值都包含在RetentionPolicy枚举中:CLASS(默认值——能被包含到class文件中,但是在运行时访问不到),SOURCE(创建class文件的时候会被编译器丢弃),RUNTIME(能够在运行过程中访问到)。

  • @Target: 声明注解类型能够注解的元素类型。可选的值包含在ElementType枚举中:ANNOTATION_TYPE(用于注解类型),CONSTRUCTOR(用于构造方法),FIELE(用于成员变量),LOCAL_VARIABLE(用于局部变量),METHOD(用于方法),PACKAGE(用于包),PARAMETER(用于方法参数),TYPE(用于类、接口、枚举)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值