什麼是註解?
註解是給編譯器、工具或執行期框架看的結構化元資料,不同於單純的註解。JDK 5 導入,常見用途:編譯檢查、程式碼生成、執行期行為注入(如 Spring、JUnit)。
三大內建標準註解
| 註解 | 用途 | 範例 |
@Override | 標示方法覆寫父類別/介面方法,編譯器檢查簽名是否匹配 | @Override public String toString() |
@Deprecated | 標示 API 已過時,編譯器發出警告 | @Deprecated public void oldMethod() |
@SuppressWarnings | 壓制特定編譯器警告 | @SuppressWarnings("unchecked") |
元註解——註解的註解
| 元註解 | 說明 | 常用值 |
@Retention | 生命週期保留範圍 | SOURCE(源碼)、CLASS(預設,位元碼)、RUNTIME(執行期可反射) |
@Target | 可標註的程式元素類型 | TYPE, METHOD, FIELD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE, ANNOTATION_TYPE, PACKAGE, TYPE_PARAMETER, TYPE_USE |
@Documented | 包含於 Javadoc 輸出 | — |
@Inherited | 子類別自動繼承父類別的此註解(僅限 TYPE) | — |
@Repeatable | Java 8+ 允許同一位置重複標註 | 配合容器註解 |
@Native | 提示常數可能被原生程式碼引用 | — |
自訂註解範例
// 1. 基本定義
public @interface MyAnnotation {
String who();
int age();
String gender();
}
// 2. 帶預設值
public @interface YouAnnotation {
String who() default "Tom";
int age() default 18;
String gender() default "unknown";
}
// 3. 陣列屬性(慣用 value 名稱可省略屬性名)
public @interface TheyAnnotation {
String[] value();
}
// 4. 完整元註解修飾:執行期可反射、標註方法/欄位、納入 Javadoc、可繼承
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.FIELD})
@Documented
@Inherited
public @interface DbConfig {
String driver() default "com.mysql.jdbc.Driver";
String url() default "jdbc:mysql://localhost:3306/test";
String user() default "root";
String password() default "1234";
}
反射讀取註解實戰:資料庫連線配置
public class DbUtil {
@DbConfig(url = "jdbc:mysql://prod:3306/app", user = "app_user")
public static Connection getConnection() throws Exception {
// 1. 取得當前方法的 Method 物件
Method m = DbUtil.class.getMethod("getConnection");
// 2. 讀取註解
DbConfig cfg = m.getAnnotation(DbConfig.class);
// 3. 使用屬性值
Class.forName(cfg.driver());
return DriverManager.getConnection(cfg.url(), cfg.user(), cfg.password());
}
}
進階應用場景
- 參數驗證框架:
@NotNull, @Size(min=1,max=20) + 方法攔截器自動驗證。
- 路由映射:
@Get("/user/{id}") 對應 Controller 方法(Spring MVC 風格)。
- 序列化控制:
@JsonIgnore, @JsonProperty("name")(Jackson)。
- 測試框架:
@Test, @BeforeEach, @ParameterizedTest(JUnit 5)。
- 編譯期處理:Lombok
@Getter/@Setter、MapStruct @Mapper 生成程式碼。
最佳實踐建議
- 註解屬性盡量提供
default 值,降低使用門檻。
- 執行期需反射的註解必須加上
@Retention(RUNTIME)。
- 限制
@Target 避免濫用(如只允許標註方法)。
- 複雜配置優先考慮 YAML/Properties + @ConfigurationProperties,註解僅作為輕量標記。