在 Java 開發中,註解已經成為不可或缺的工具。它不僅能標記程式碼,更能通過反射機制在編譯期、類載入期或執行期發揮作用。本文將系統梳理 Java 註解的核心概念、內建註解、元註解以及自定義註解的實戰應用。
註解(Annotation)本質上是一個繼承了 java.lang.annotation.Annotation 介面的特殊介面,使用 @interface 關鍵字定義。它就像貼在程式碼上的標籤,編譯器、開發工具或執行期框架可以通過反射讀取這些標籤,進而執行相應邏輯。
用於方法宣告,表示該方法覆寫父類方法。若方法簽名錯誤(如大小寫不匹配 ToString() vs toString()),編譯器會直接報錯,避免低級錯誤進入生產環境。
標記類、方法或欄位已過時,不建議繼續使用。編譯器會在使用處發出警告,提醒開發者遷移到新 API。
壓制編譯器警告,常見參數有 unchecked(泛型未檢查)、deprecation(使用過時 API)等。
元註解用於修飾其他註解的定義,決定註解的生命週期、作用目標等核心屬性。
定義註解資訊保留到哪個階段,對應 RetentionPolicy 三種枚舉值:
限制註解可應用的程式元素類型,對應 ElementType 枚舉:
TYPE:類、介面、枚舉METHOD:方法FIELD:欄位(包含枚舉常數)PARAMETER:方法參數CONSTRUCTOR:建構子LOCAL_VARIABLE:區域變數ANNOTATION_TYPE:另一個註解PACKAGE:套件宣告例如 @Target(ElementType.METHOD) 限定該註解只能用在方法上,若強行用在類上會編譯報錯。
自定義註解語法類似介面,方法即為屬性,支援預設值:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
String value() default "defaultVal"; // 單一屬性名為 value 時使用可省略屬性名
String hello() default "gege";
String world();
int[] array() default {2, 4, 5, 6};
TrafficLamp lamp(); // 枚舉類型屬性
TestAnnotation lannotation() default @TestAnnotation(value="ddd"); // 註解嵌套
Class<?> style() default String.class; // Class 類型屬性
}
屬性類型僅限:基本型別、String、Class、枚舉、註解、以及上述類型的一維陣列。
只有標記 @Retention(RetentionPolicy.RUNTIME) 的註解才能在執行期通過反射獲取:
// 類級別註解讀取
if (MyTest.class.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation ann = MyTest.class.getAnnotation(MyAnnotation.class);
System.out.println(ann.hello()); // 輸出屬性值
}
// 方法級別註解讀取
Method method = MyTest.class.getMethod("output");
if (method.isAnnotationPresent(MyAnnotation.class)) {
MyAnnotation ann = method.getAnnotation(MyAnnotation.class);
// 獲取陣列、嵌套註解、Class 等複雜屬性
System.out.println(ann.array().length);
System.out.println(ann.lannotation().value());
System.out.println(ann.style());
}
// 獲取方法上所有 RUNTIME 註解
Annotation[] annotations = method.getAnnotations();
for (Annotation a : annotations) {
System.out.println(a.annotationType().getName());
}
value,使用時可直接寫 @MyAnnotation("xxx") 省略屬性名。java.lang.annotation.Annotation 介面。@Documented 元註解可讓 Javadoc 包含該註解資訊。掌握註解機制,不僅能看懂 Spring、Hibernate 等主流框架的核心運作原理,更能編寫優雅的聲明式程式碼,實現關注點分離與框架級擴展。