Annotation(註解) 是 JDK 5.0 引入的一種元程式設計機制,讓開發者能將元資料(Metadata)關聯到程式元素(套件、類別、方法、欄位、參數、區域變數等)。註解本質上是一個介面(繼承 java.lang.annotation.Annotation),程式可透過反射讀取其屬性值,但註解本身不影響程式碼執行邏輯——JVM 執行時會忽略它們,需配合編譯期處理器(APT)、執行期框架(Spring、Hibernate 等)或工具(javadoc)才能發揮作用。
| 分類 | 用途 | 典型例子 |
|---|---|---|
| 文件生成 | 從原始碼標記自動產出文件 | Javadoc 標籤 @param、@return |
| 程式碼分析 | 靜態分析、找潛在 Bug、架構檢查 | FindBugs、Error Prone、Checkstyle 自訂規則 |
| 編譯檢查 | 編譯期強制語義約束 | @Override、@Deprecated、@SuppressWarnings |
@Override。value()。如 @SuppressWarnings("unchecked")。@Override、@Deprecated、@SuppressWarnings、@SafeVarargs、@FunctionalInterface 等。java.lang.annotation。包含 @Target、@Retention、@Documented、@Inherited、@Repeatable、@Native。@Autowired、JPA @Entity)。
class Fruit {
public void displayName() { System.out.println("水果"); }
}
class Orange extends Fruit {
@Override
public void displayName() { System.out.println("橘子"); } // 正確
}
class Apple extends Fruit {
@Override
public void displayname() { System.out.println("蘋果"); } // 編譯錯誤:方法名拼寫錯誤,未真正覆寫
}
僅能修飾方法,防止拼寫錯誤、參數不符導致「以為覆寫實則多載」。
class AppleService {
@Deprecated
public void showTaste() { System.out.println("脆甜"); }
public void showTaste(int typeId) { /* 新版多型重載 */ }
}
@deprecated 標籤說明替代方案。
@SuppressWarnings({ "rawtypes", "unchecked" })
public List<Fruit> getFruitList() {
List<Fruit> list = new ArrayList(); // 原始類型警告
return list;
}
@SuppressWarnings("unused")
public void test() {
String unusedVar = "hello"; // 故意不使用,抑制未使用變數警告
}
| 常用參數值 | 含義 |
|---|---|
deprecation | 使用過時 API |
unchecked | 泛型未檢查轉換(如原始集合賦值給泛型變數) |
fallthrough | switch 缺少 break 直落 |
serial | 可序列化類別缺少 serialVersionUID |
all | 抑制以上所有 |
| 元註解 | 作用 | 關鍵屬性 |
|---|---|---|
@Target | 限定註解可用程式元素 | ElementType[] value():TYPE、FIELD、METHOD、PARAMETER、CONSTRUCTOR、LOCAL_VARIABLE、PACKAGE、MODULE 等 |
@Retention | 定義註解保留階段 | RetentionPolicy value():SOURCE(源碼)、CLASS(預設、class 檔)、RUNTIME(執行期可反射) |
@Documented | 標示應被 javadoc 納入 API 文件 | 標記註解,無屬性 |
@Inherited | 允許子類別繼承父類別的此註解(僅限 TYPE) | 標記註解,配合 RUNTIME 反射時向上查找 |
@Repeatable | 允許同一元素重複套用該註解(JDK 8+) | Class<? extends Annotation> value() 指定容器註解 |
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface FruitName {
String value() default ""; // 單一屬性慣命名 value()
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface FruitColor {
enum Color { RED, GREEN, BLUE }
Color fruitColor() default Color.GREEN;
}
@interface 定義,隱含繼承 Annotation 介面。public 或預設(package-private)修飾。default 指定預設值。javax.annotation.processing.Processor,掃描源碼註解生成新原始碼/資源/類別(如 Lombok、MapStruct、Dagger)。AnnotatedElement.getAnnotation()、getAnnotations() 讀取 RUNTIME 註解屬性驅動邏輯(Spring AOP、JAX-RS 路由、JSON 序列化配置)。註解 = 標準化的元資料載體。
它不執行業務邏輯,但為工具鏈、框架、團隊協作提供結構化語義錨點。
善用@Target/@Retention明確語義邊界,配合 APT 或反射,將「約定」轉為「程式可驗證的契約」。