JDK5.0中注释(Annotation)的用法

很多API都需要相当数量的样板代码,比如,为了编写一个JAX-RPC的WEB服务,你需要提供一个接口和一个实现类。如果这个程序已经被加了注释Annotations以说明那个方法需要被远程调用,那么我们可以一个工具去自动生成这些样板代码。

还有一些API需要在程序代码另外维护一些文件,比如JavaBean需要一个BeanInfo类,EJB需要一个部署描述文件。如果我们能够把这些需要另外维护的文件内容以注释Annotation的方式和代码放在一起维护,一定会更加方便同时也减少出错的机会。

Java平台已经有了一些特别的注释的机制。比如transient修饰符就是一个特别的注释,表明这个字段应该被序列化子系统忽略;@deprecated javadoc标签是一个特别的标签来说明某个方法已经不再被使用了。JDK5.0提供了一个让我们自己定义我们自己注释的功能,这个功能包含了如何定义注释类型的语法,声明注释的语法,读取注释的API,一个类文件保存注释(译者注:注释可以被看作一个类,我们需要用一个.java文件保存我们自己定义的注释源码)和一个注释处理的工具。

注释并不影响代码的语义,但却影响用于处理包含有注释的程序代码的工具的处理方式,使他们(工具)能够影响运行状态的程序的语义。注释可以从源代码中读取,从编译后的.class文件中读取,也可以通过反射机制在运行时读取。

注释是JavaDoc标签的补充。一般情况下,如果我们的主要目标是影响或者产生文档,那么我们应该使用JavaDoc;否则,我们应该使用注释Annotations。

一般的应用程序开发人员可能从不需要定义一个注释类型,但定义我们自己的注释类型并不复杂。注释类型的定义跟定义一个接口相似,我们需要在interface这个关键字前面加上一个@符号。注释中的每一个方法定义了这个注释类型的一个元素,注释中方法的声明中一定不能包含参数,也不能抛出异常;方法的返回值被限制为简单类型、String、Class、emnus、注释,和这些类型的数组。方法可以有一个缺省值。这里是一个注释类型定义的例子:

/*** Describes the Request-For-Enhancement(RFE) that led* to the presence of the annotated API element.*/public @interface RequestForEnhancement {    int    id();    String synopsis();    String engineer() default "[unassigned]";     String date();    default "[unimplemented]"; }

一旦定义好了一个注释类型,你就可以用来作注释声明。注释一中特殊的修饰符,在其他修饰符(比如public,static,或者final等)使用地方都可以使用。按照惯例,注释应该放在其他修饰符的前面。注释的声明用@符号后面跟上这个注释类型的名字,再后面跟上括号,括号中列出这个注释中元素/方法的key-value对。值必须是常量。这里是一个例子,使用上面定义的注释类型:

@RequestForEnhancement(

    id       = 2868724,

    synopsis = "Enable time-travel",

    engineer = "Mr. Peabody",

    date     = "4/1/3007"

)

public static void travelThroughTime(Date destination) { ... }

 

没有元素/方法的注释被成为标记(marker)注释类型,例如

 

/**

* Indicates that the specification of the annotated API element

* is preliminary and subject to change.

*/

public @interface Preliminary { }

 

标记注释在使用的时候,其后面的括号可以省略,例如:

@Preliminary public class TimeTravel { ... }

如果注释中仅包含一个元素,这个元素的名字应该为value,例如:

/**

* Associates a copyright notice with the annotated API element.

*/

public @interface Copyright { String value(); }

如果元素的名字为value,使用这个注释的时候,元素的名字和等号可以省略,如:

@Copyright("2002 Yoyodyne Propulsion Systems")

public class OscillationOverthruster { ... }

为了将上面提到的东西结合在一起,我们创建了一个简单的基于注释的测试框架。首先我们需要一个标记注释类型用以说明一个方法是一个测试方法,并被测试工具执行。

 

import java.lang.annotation.*;

 

/**

* Indicates that the annotated method is a test method.

* This annotation should be used only on parameterless static methods.

*/

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface Test { }

 

我们可以注意到这个注释类型本省也被注释了,这种注释叫做元注释。第一注释(@Retention(RetentionPolicy.RUNTIME))表示这种类型的注释被VM保留从而使其能够通过反射在运行时读取;第二个注释@Target(ElementType.METHOD)表示这种注释只能用来注释方法。

 

下面是一个简单的类,其中的几个方法被加了上面的注释:

 

public class Foo {

    @Test public static void m1() { }

    public static void m2() { }

    @Test public static void m3() {

        throw new RuntimeException("Boom");

    }

    public static void m4() { }

    @Test public static void m5() { }

    public static void m6() { }

    @Test public static void m7() {

        throw new RuntimeException("Crash");

    }

    public static void m8() { }

}

 

这里是测试工具:

 

import java.lang.reflect.*;

 

public class RunTests {

   public static void main(String[] args) throws Exception {

      int passed = 0, failed = 0;

      for (Method m : Class.forName(args[0]).getMethods()) {

         if (m.isAnnotationPresent(Test.class)) {

            try {

               m.invoke(null);

               passed++;

            } catch (Throwable ex) {

               System.out.printf("Test %s failed: %s %n", m, ex.getCause());

               failed++;

            }

         }

      }

      System.out.printf("Passed: %d, Failed %d%n", passed, failed);

   }

}

 

这个工具用一个类名作为参数,遍历这个类中的所有方法,并调用其中被加了@Test注释的方法。如果一个方法抛出了一个异常,那么这个测试就失败了,最终的测试结果被打印了出来。下面是程序运行的结果:

 

$ java RunTests Foo

Test public static void Foo.m3() failed: java.lang.RuntimeException: Boom

Test public static void Foo.m7() failed: java.lang.RuntimeException: Crash

Passed: 2, Failed 2

 

 

虽然这个测试工具只是一个玩具,但他显示了注释的强大的功能。

时间: 2024-10-06 10:16:16

JDK5.0中注释(Annotation)的用法的相关文章

关于JDK5.0中预定义的解释

我们先来看一下,下面这段代码: public class B extends A { @Override public void test1() { // TODO Auto-generated method stub super.test1(); } } 上面这段代码很简单,创建一个类,类的名字为B 同时让这个B类继承与A类,在A类中 有一个方法叫 test1 ,现在我们想在B类中覆盖A类的test1方法,我们会看到代码中会出 现 @Override 一句注释,它是用来干什么的呢?有很多学习J

ASP.NET2.0中的ClientScriptManager 类用法

asp.net|client ASP.NET2.0中的ClientScriptManager 类用法-如何添加客户端事件 在ASP.NET2.0中,ClientScriptManager 类通过键 String 和 Type 唯一地标识脚本.具有相同的键和类型的脚本被视为重复脚本.因此,我们可以使用脚本类型来避免混淆可能用在页中的来自不同用户控件的相似脚本. <html>  <head>    <title>ClientScriptManager Example<

J2SE5.0实例---注释(annotation)

j2se 注释(annotation) J2SE 5.0通过引入注释(Annotation)的概念添加了对元数据的支持. 一个@xxx形式的注释可以当成一个修饰符来使用,它可以放在任何一个修饰符可以出现的地方.public,static,final都是java语言的修饰符,注释可以写在它们可以出现的任何地方. 举个例子,可以看下面一段代码: public class AnnotationExample {   public @Override int hashCode() {      retu

JDK5.0中的内置工具简介

JDK5.0里面加入了jstack, jconsole, jinfo, jmap, jdb, jstat, jps, 下面对这些工具做简单介绍:jstack -- 如果java程序崩溃生成core文件,jstack工具可以用来获得core文件的java stack和native stack的信息,从而可以轻松地知道java程序是如何崩溃和在程序何处发生问题.另外,jstack工具还可以附属到正在运行的java程序中,看到当时运行的java程序的java stack和native stack的信息

ASP.NET 2.0中的ClientScriptManager类用法—如何添加客户端事件

在ASP.NET2.0中,ClientScriptManager 类通过键 String 和 Type 唯一地标识脚本.具有相同的键和类型的脚本被视为重复脚本.因此,我们可以使用脚本类型来避免混淆可能用在页中的来自不同用户控件的相似脚本. <html> <head> <title>ClientScriptManager Example</title> </head> <body> <form id="Form1&quo

C# 2.0 中关于泛型的用法实例

1. 定义泛型类 using System;using System.Collections;using System.Collections.Generic;using System.Text; namespace WindowsApplication1{    class BList<T>    {        ArrayList arr = new ArrayList();         public T this[int i]        {            get    

JDK5.0的11个主要新特征

1  泛型(Generic) 1.1 说明 增强了java的类型安全,可以在编译期间对容器内的对象进行类型检查,在运行期不必进行类型的转换.而在j2se5之前必须在运行期动态进行容器内对象的检查及转换 减少含糊的容器,可以定义什么类型的数据放入容器 ArrayList<Integer> listOfIntegers; // <TYPE_NAME> is new to the syntaxInteger integerObject;listOfIntegers = new Array

J2SE5.0中最有趣的新特性:注释(annotation)

本文为原创,如需转载,请注明作者和出处,谢谢! 本文曾发表于IT168:http://tech.it168.com/j/e/2006-09-29/200609291054707.shtml     本文将向你介绍J2SE5.0中的新特性之一:注释.本文将从什么是注释:J2SE5.0中预定义的注释:如何自定义注释:如何对注释进行注释以及如何在程序中读取注释5个方面进行讨论. 一.什么是注释     说起注释,得先提一提什么是元数据(metadata).所谓元数据就是数据的数据.也就是说,元数据是描

JDK/JRE5.0中对于IPv6的支持-解读JDK5.0对IPv6网络编程的支持

编程|网络 JDK5.0 Document:Networking IPv6 User Guide for JDK/JRE 5.0This document covers the following topics:Overview Supported Operating Systems Using IPv6 in Java Details on IPv6 Support in Java Special IPv6 Address Types IPv6-Related System Propertie