注解Annotation

注解(Annotation)是Java5中的新特性,一直看到很多项目在使用,但是自己一直不是很了解,现在有机会学习了一下,记录下来,今后用得着。

1.注解可以做什么?

注解将一些系统所需的数据信息(不方便用Java语言来表达),加入到了Java源代码中,而不需要额外的信息提供者。比如配置信息、一些样板文件(接口文件)等。可以通过在代码中添加注解,来直接配置你的系统。

著名的Java单元测试框架Junit-4就是大量使用了注解的功能,加入到了其单元测试中,方面了用户使用JUnit进行测试,用户只需要在想要测试的方法上添加@Test 这样的标签就可以将该方法变为一个单元测试用例。

下面,我将仿照JUnit的测试框架来简单介绍一下注解功能(例子来自于java.sun.com)

2.注解怎么使用

我把注解的使用分为三个步骤:

第一,定义注解

第二,给源程序添加注解

第三,解析注解(实际工作在这里完成)


首先看定义注解


注解的定义看起来和定义接口差不多,就是在interface关键字前多一个@标签

Requestforenhancement注解的定义代码代码 

    /**  
     * Describes the Request-For-Enhancement(RFE) that led  
     * to the presence of the annotated API element.  
     */  

Requestforenhancement注解的定义代码代码

    @Target(ElementType.METHOD)  
    @Retention(RetentionPolicy.RUNTIME)  
    public @interface RequestForEnhancement {  
        int    id();  
        String synopsis();  
        String engineer() default "[unassigned]";   
        String date();    default "[unimplemented]";   
    }  


其中的id()、synopsis()可以认为是该注解的元素,或者属性,这些方法声明不能有任何参数,或者抛出异常,可以通过default 来定义它的默认值。而且这些类型只能是原语类型、String、Annotation或者这些类型的数组。

最上面的@Target表面了改注解使用的范围(是一个方法还是一个类,或者一个域),@Retention表面了注解可以用在哪个级别上(源代码中、类文件中、还是运行时)

 

这样,便定义了一个注解

 

接下来给源程序添加注解:

Java代码:

    @RequestForEnhancement(  
        id       = 2868724,  
        synopsis = "Enable time-travel",  
        engineer = "Mr. Peabody",  
        date     = "4/1/3007"  
    )  
    public static void travelThroughTime(Date destination) { ... }  
这样就使用刚才定义的RequestForEnhancement注解,描述了一个方法,可以看见在()中,定义了给该注解的各个元素的参数,就相当于初始化了该注解

 

最后解析注解,这里我们使用一个简单的测试框架来表述

定义一个Test注解,使用在运行时,定义在方法上,它没有任何方法,只是一个标注

在解析程序中,获取该标注,并采取相应动作。在这里,使用了Test标签标注的方法,都将被测试,并形成测试结果。

Java代码 :

    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 { }  

添加将被测试的方法:

Java代码:


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() { }  
    }  



在这里用@Test标签标注了m1 m3 m5 m7方法,这些方法将在运行测试用例时被测试。

在该类中运行了测试用例,它使用反射机制,调用了被标注为@Test标签的方法,如果抛出异常则认为测试没有通过,反之则通过。

Java代码

    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);  
       }  
    }  

在这里,可以讲上面的这些类、注解可以和JUnit中的进行一个对比

@Test就是JUnit框架中的@Test

被标注的方法将被测试

RunTest类就相当于手动启动JUnit进行单元测试时运行的org.junit.runner.JUnitCore.runClasses(不是使用IDE启动测试用例,如果使用Eclipse类似的IDE,你可能只是点击一个Run As JUnit)

 

这样,就通过注解完成了一个简单的测试框架

 

详细信息可以查看





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值