註解是 Java 5 引入的元資料機制,讓程式碼攜帶額外語義,被編譯器、工具、框架解讀。本文系統梳理:註解與文件註解的本質差異、內建註解、自訂註解與元註解、保留策略、反射讀取、Javadoc 規範與實戰應用。
| 維度 | Annotation (註解) | Javadoc (文件註解) |
|---|---|---|
| 目標受眾 | 編譯器、JVM、框架、工具 | 開發者、API 使用者 |
| 語法 | @AnnotationName | /** ... */ |
| 保留期 | SOURCE / CLASS / RUNTIME | 僅原始碼,經 javadoc 工具生成 HTML |
| 核心用途 | 編譯檢查、程式碼分析、執行期行為注入 | 生成 API 文件、說明用法 |
@Override:強制檢查方法確實覆寫父類,防止拼錯方法名/簽名不符。@Deprecated:標記不建議使用,IDE 會劃刪除線並提示替代方案。@SuppressWarnings("unchecked" | "deprecation" | "rawtypes" | "all" ...):壓制特定編譯警告。| 元註解 | 作用 | 關鍵屬性 |
|---|---|---|
@Target | 限制註解可用位置 | ElementType.TYPE/METHOD/FIELD/PARAMETER... |
@Retention | 指定保留階段 | SOURCE / CLASS / RUNTIME |
@Documented | 納入 Javadoc | 無 |
@Inherited | 允許子類繼承 | 僅對 TYPE 有效 |
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ApiSpec {
String author() default "unknown";
String version() default "1.0";
String description() default "";
boolean deprecated() default false;
}
@Retention(SOURCE) @interface A {} // 僅源碼,編譯器丟棄
@Retention(CLASS) @interface B {} // 進 class 檔,JVM 載入時丟棄(預設)
@Retention(RUNTIME) @interface C {} // JVM 保留,可用反射讀取
只有 RUNTIME 註解能在執行期透過 getAnnotation() 取得。
@ApiSpec(author = "Alice", version = "2.1", description = "使用者查詢")
public void queryUser(@ApiSpec(description = "使用者 ID") Long id) { ... }
// 讀取方法註解
Method m = UserService.class.getMethod("queryUser", Long.class);
ApiSpec spec = m.getAnnotation(ApiSpec.class);
System.out.println(spec.author()); // Alice
System.out.println(spec.description()); // 使用者查詢
// 讀取參數註解
Annotation[][] paramAnnos = m.getParameterAnnotations();
for (Annotation a : paramAnnos[0]) {
if (a instanceof ApiSpec) System.out.println(((ApiSpec)a).description()); // 使用者 ID
}
Spring、Hibernate、JPA、MyBatis 等大量使用註解替代 XML:
@Entity @Table(name = "users")
public class User {
@Id @GeneratedValue Long id;
@Column(name = "email", nullable = false, unique = true) String email;
}
原理:容器啟動掃描類路徑,反射讀取註解元資料,建構 BeanDefinition / EntityMapping 等內部模型。
@param 參數說明(多個各佔一行)@return 回傳值說明@throws / @exception 拋出異常說明@see 參考連結@since 起始版本@author / @version 作者/版本(類級)/**
* 依 ID 查詢使用者。
* @param id 使用者主鍵,不可為 null
* @return 使用者實體;若不存在回傳 null
* @throws DataAccessException 資料庫存取失敗
* @see UserRepository#findByEmail(String)
* @since 2.3
*/
public User findById(Long id) throws DataAccessException { ... }
/**
* 使用者領域服務,處理核心業務規則。
* @author Team Alpha
* @version 3.1.0
* @since 2.0
*/
public class UserDomainService { ... }
# 指令列 javadoc -d docs -sourcepath src -subpackages com.myapp # Maven mvn javadoc:javadoc
註解賦予 Java 程式碼「可被機器理解的語義」,配合反射與 APT (Annotation Processing Tool),構建了現代框架生態的基石。文件註解則守護 API 的可讀性與傳承性。善用兩者,寫出既自描述又易維護的專業程式碼。