Java5中的註解功能(Annotation)

註解(Annotation)是Java5中的新特性,一直看到很多項目在使用,但是自己一直不是很瞭解,現在有機會學習了一下,記錄下來,今後用得着。

1.註解可以做什麼?

註解將一些系統所需的數據信息(不方便用Java語言來表達),加入到了Java源代碼中,而不需要額外的信息提供者。比如配置信息、一些樣板文件(接口文件)等。可以通過在代碼中添加註解,來直接配置你的系統。

著名的Java單元測試框架Junit-4就是大量使用了註解的功能,加入到了其單元測試中,方面了用戶使用JUnit進行測試,用戶只需要在想要測試的方法上添加@Test 這樣的標籤就可以將該方法變爲一個單元測試用例。

下面,我將仿照JUnit的測試框架來簡單介紹一下註解功能(例子來自於java.sun.com)

2.註解怎麼使用

我把註解的使用分爲三個步驟:

第一,定義註解

第二,給源程序添加註解

第三,解析註解(實際工作在這裏完成)

 

首先看定義註解

 

註解的定義看起來和定義接口差不多,就是在interface關鍵字前多一個@標籤

 

/**
 * Describes the Request-For-Enhancement(RFE) that led
 * to the presence of the annotated API element.
 */
@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表面了註解可以用在哪個級別上(源代碼中、類文件中、還是運行時)

 

這樣,便定義了一個註解

 

接下來給源程序添加註解:

 

@RequestForEnhancement(
    id       = 2868724,
    synopsis = "Enable time-travel",
    engineer = "Mr. Peabody",
    date     = "4/1/3007"
)
public static void travelThroughTime(Date destination) { ... }

 

 這樣就使用剛纔定義的RequestForEnhancement註解,描述了一個方法,可以看見在()中,定義了給該註解的各個元素的參數,就相當於初始化了該註解

 

最後解析註解,這裏我們使用一個簡單的測試框架來表述

定義一個Test註解,使用在運行時,定義在方法上,它沒有任何方法,只是一個標註

在解析程序中,獲取該標註,並採取相應動作。在這裏,使用了Test標籤標註的方法,都將被測試,並形成測試結果。

 

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

 

添加將被測試的方法:

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標籤的方法,如果拋出異常則認爲測試沒有通過,反之則通過。

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)

 

這樣,就通過註解完成了一個簡單的測試框架

 

詳細信息可以查看

http://java.sun.com/j2se/1.5.0/docs/guide/language/annotations.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章