From Gossip@Openhome

Java Gossip: 自訂 Annotation 型態

您可以自訂Annotation型別,並使用這些自訂的Annotation型別在程式碼中使用 Annotation,這些Annotation將提供資訊給您的程式碼分析工具。

首先來看看如何定義Marker Annotation,也就是Annotation名稱本身即提供資訊,對於程式分析工具來說,主要是檢查是否有Marker Annotation的出現,並作出對應的動作。

要定義一個Annotation所需的動作,就類似於定義一個介面(interface),只不過您使用的是@interface,例如定義一個 Debug Annotation型態:

  • Debug.java
package onlyfun.caterpillar;
public @interface Debug {}

由於是個Marker Annotation,所以沒有任何的成員在媕Y,編譯完成後,您就可以在程式碼中使用這個Annotation了,例如:
  • SomeObject.java
package onlyfun.caterpillar;

import java.util.*;

public class SomeObject {

@Debug
public void doSomething() {
// ....
}
}

接著來看看如何定義一個Single-value Annotation,它只有一個成員,名稱為value,例如您可以提供Debug Annotation更多資訊:
  • Debug.java
package onlyfun.caterpillar;

public @interface Debug {
String value();
}

實際上您定義了value()方法,編譯器在編譯時會自動幫您產生一個value的變數成員,接著在使用Debug Annotation時要指定值,例如:
  • SomeObject.java
package onlyfun.caterpillar;

import java.util.*;

public class SomeObject {
@Debug("unit test")
public void doSomething() {
// ....
}
}

@Debug("unit test")實際上是@Debug(value="unit test")的簡便寫法,如果是陣列值,例如:
  • Debug.java
package onlyfun.caterpillar;

public @interface Debug {
String[] value();
}

則使用Annotation時,可以寫成@Debug({"value1", "value2"}),或是@Debug(value={"value1", "value2"})。

您也可以對成員設定預設值,使用default關鍵字即可,例如:

  • Debug.java
package onlyfun.caterpillar;

public @interface Debug {
String value() default "none";
}

這麼一來如果您使用@Debug時沒有指定值,則預設就是"none"。

您也可以為Annotation定義額外的成員,以提供額外的資訊給分析工具,例如:

  • Debug.java
package onlyfun.caterpillar;

public @interface Debug {
public enum Level {NONE, UNIT, INTEGRATION, FUNCTION};

Level level() default Level.NONE;
String name();
String tester();
}

則您可以如下使用這個Annotation:
  • SomeObject.java
package onlyfun.caterpillar;

import java.util.*;

public class SomeObject {
@Debug(
level = Debug.Level.UNIT,
name = "some test",
tester = "justin"
)
public void doSomething() {
// ....
}
}

@interface實際上是自動繼承自java.lang.annotation.Annotation,所以定義Annotation時不能繼承其它 Annotation或是interface。