@Override:編譯期檢查方法確實覆寫父類別@Deprecated:標記過時API,編譯產生警告@SuppressWarnings:抑制特定編譯警告自訂註解必須理解四大核心元註解(皆在java.lang.annotation套件):
| 元註解 | 用途 | 關鍵值 |
|---|---|---|
@Target | 限定註解可標註位置 | ElementType:TYPE、FIELD、METHOD、PARAMETER、CONSTRUCTOR、LOCAL_VARIABLE、ANNOTATION_TYPE、PACKAGE |
@Retention | 定義註解保留階段 | RetentionPolicy:SOURCE(僅原始碼)、CLASS(預設,含class檔)、RUNTIME(JVM可見,可反射讀取) |
@Documented | 納入Javadoc文件 | 標記型,無參數 |
@Inherited | 允許子類別繼承父類別註解 | 僅對TYPE類型註解有效 |
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Description {
String value(); // 單一屬性慣命名為value
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Name {
String originate();
String community(); // 多屬性需指定名稱
}
屬性限制:僅支援基本型別、String、Enum、Class、註解型別及其陣列;存取修飾符僅public或預設;無方法主體,類似介面宣告。
@Description("javaeye,做最棒的軟體開發交流社群")
public class JavaEyer {
@Name(originate="創始人:robbin", community="javaEye")
public String getName() { return null; }
@Name(originate="創始人:江南白衣", community="springside")
public String getName2() { return "借用兩位的id一用"; }
}
public class TestAnnotation {
public static void main(String[] args) throws Exception {
Class<?> clazz = Class.forName("lighter.javaeye.com.JavaEyer");
// 讀取類別級註解
if (clazz.isAnnotationPresent(Description.class)) {
Description desc = clazz.getAnnotation(Description.class);
System.out.println("描述:" + desc.value());
}
// 讀取方法級註解
for (Method m : clazz.getMethods()) {
if (m.isAnnotationPresent(Name.class)) {
Name name = m.getAnnotation(Name.class);
System.out.println(name.originate());
System.out.println("建立的社群:" + name.community());
}
}
}
}
輸出結果:
描述:javaeye,做最棒的軟體開發交流社群 ----------------- 創始人:robbin 建立的社群:javaEye 創始人:江南白衣 建立的社群:springside
掌握基礎後,可延伸至編譯期註解處理器(APT)自動產生代碼、執行期框架整合(如Spring的@Autowired、JPA的@Entity)、測試框架(JUnit@Test)等實戰場景。