註解自 Java 5 引入,本質是附加在程式碼上的元資料。它們不直接改變程式邏輯,但能被編譯器、建構工具或運行時框架讀取,從而影響建構流程、代碼生成或運行行為。
| 保留策略 | 常數 | 適用階段 | 典型用途 |
|---|---|---|---|
| 源碼級 | RetentionPolicy.SOURCE | 僅存在於 .java 檔 | @Override、@SuppressWarnings,編譯後丟棄 |
| 類別級(預設) | RetentionPolicy.CLASS | 存在於 .class 檔,不可反射訪問 | 位元碼操作工具(如 Lombok、MapStruct) |
| 運行時 | RetentionPolicy.RUNTIME | JVM 運行時可反射讀取 | Spring、JUnit、Hibernate 等框架核心機制 |
標記不再推薦使用的 API,編譯器會發出警告。建議搭配 Javadoc @deprecated 說明替代方案。
@Deprecated
/** @deprecated 請改用 {@link MyNewComponent} */
public class MyComponent { }
驗證方法確實覆寫了父類/介面方法。雖非強制,但強烈建議加上:若父類方法簽名變更,編譯器會即時報錯,避免無意中斷繼承鏈。
public class Child extends Parent {
@Override
public void doSomething() { ... }
}
抑制特定編譯器警告。遵循就近原則:標註在最小範圍(方法而非類別),避免掩蓋真實問題。
@SuppressWarnings("unchecked")
public void legacyMethod() { ... }
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface ApiEndpoint {
String path() default "/";
HttpMethod method() default HttpMethod.GET;
int version() default 1;
}
@interface 關鍵字宣告註解類型default 指定預設值,使用時可省略| 元註解 | 作用 | 關鍵屬性 |
|---|---|---|
@Retention | 生命週期 | RetentionPolicy 三種策略 |
@Target | 修飾目標 | ElementType:TYPE、METHOD、FIELD、PARAMETER 等 |
@Inherited | 允許子類繼承 | 僅對類別級註解生效 |
@Documented | 包含於 Javadoc | 無屬性 |
@Repeatable | 可重複標註 | Java 8+,需配合容器註解 |
javax.annotation.processing.Processor// 讀取類別註解
ApiEndpoint ann = MyClass.class.getAnnotation(ApiEndpoint.class);
if (ann != null) {
System.out.println("Path: " + ann.path());
}
// 讀取方法註解
for (Method m : MyClass.class.getDeclaredMethods()) {
if (m.isAnnotationPresent(ApiEndpoint.class)) {
ApiEndpoint ep = m.getAnnotation(ApiEndpoint.class);
// 處理路由註冊等邏輯
}
}
注意:反射有效能開銷,高頻熱點路徑建議緩存結果或改用編譯期處理。
@Transactional 而非 @DB)@Target 精確限定修飾範圍RUNTIME,代碼生成用 SOURCE/CLASS@Documented 讓 API 使用者可見