註解本質與分類
註解是 JDK 5.0 引入的元數據,不直接影響代碼邏輯,供編譯器、工具、運行時反射讀取。分為三類:
- 標準註解:JDK 內置,如
@Override
- 元註解:註解的註解,定義註解行為,如
@Retention
- 自定義註解:業務級註解,配合處理器實現框架功能
三大標準註解
| 註解 | 目標 | 作用 |
@Override | 方法 | 檢查是否正確覆寫父類方法,防止拼寫錯誤 |
@Deprecated | 類/方法/字段 | 標記過時,編譯器警告,建議替代方案 |
@SuppressWarnings | 任意 | 抑制特定編譯警告(unchecked、deprecation、rawtypes 等) |
四大元註解:定義註解的「註解」
@Target:註解可用位置
@Target({
ElementType.TYPE, // 類、接口、枚舉
ElementType.FIELD, // 字段
ElementType.METHOD, // 方法
ElementType.PARAMETER, // 參數
ElementType.CONSTRUCTOR, // 構造器
ElementType.LOCAL_VARIABLE, // 局部變量
ElementType.ANNOTATION_TYPE, // 註解類型
ElementType.PACKAGE, // 包
ElementType.TYPE_PARAMETER, // 類型參數 (JDK 8)
ElementType.TYPE_USE // 類型使用 (JDK 8)
})
@Retention:生命週期策略
@Retention(RetentionPolicy.SOURCE) // 僅源碼,編譯器丟棄(如 @Override)
@Retention(RetentionPolicy.CLASS) // 編譯進 class,JVM 不加載(默認)
@Retention(RetentionPolicy.RUNTIME) // 運行時可見,反射可讀(框架必備)
@Documented:納入 Javadoc
@Documented
public @interface MyAnnotation { } // 生成文檔時包含此註解
@Inherited:允許繼承
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@interface ParentAnno { }
@ParentAnno
class Parent { }
class Child extends Parent { } // Child 類可通過反射獲取 ParentAnno
自定義註解語法
標記註解(無屬性)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test { }
屬性註解(帶屬性、默認值、類型限制)
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {
int id(); // 必填
String description() default "none"; // 可選,有默認值
String[] tags() default {}; // 數組屬性
Class>[] related() default {}; // Class 類型
Priority level() default Priority.MEDIUM; // 枚舉類型
}
enum Priority { HIGH, MEDIUM, LOW }
屬性類型限制
- 八大基本類型 + String + Class + Enum + Annotation + 以上類型數組
- 禁止:包裝類、集合、自定義對象、null 值
註解處理器:反射讀取與業務邏輯
運行時處理器模式
public class UseCaseTracker {
public static void track(List useCases, Class> clazz) {
for (Method m : clazz.getDeclaredMethods()) {
UseCase uc = m.getAnnotation(UseCase.class);
if (uc != null) {
System.out.printf("Found: id=%d, desc=%s%n", uc.id(), uc.description());
useCases.remove(Integer.valueOf(uc.id()));
}
}
useCases.forEach(id -> System.out.println("Missing: " + id));
}
public static void main(String[] args) {
List ids = Arrays.asList(47, 48, 49, 50);
track(ids, PasswordUtils.class);
}
}
編譯時處理器(APT)進階
- 實現
javax.annotation.processing.Processor
- 註冊
META-INF/services/javax.annotation.processing.Processor
- 編譯期生成代碼/資源/檢查,零運行時開銷
- 典型框架:Lombok、MapStruct、Dagger、Room
典型應用場景
| 場景 | 代表框架 | 核心註解 |
| ORM 映射 | Hibernate/JPA | @Entity、@Table、@Id、@Column |
| 依賴注入 | Spring | @Autowired、@Component、@Value |
| Web 映射 | Spring MVC | @RequestMapping、@RequestBody、@PathVariable |
| 參數驗證 | Bean Validation | @NotNull、@Size、@Valid |
| 單元測試 | JUnit 5 | @Test、@BeforeEach、@ParameterizedTest |
| 代碼生成 | Lombok | @Data、@Builder、@Slf4j |
最佳實踐
- 框架註解必用
@Retention(RUNTIME),工具註解用 SOURCE
- 屬性命名遵循駝峰,布爾屬性用
enabled 而非 isEnabled
- 提供合理默認值,減少使用者樣板代碼
- 文檔化:@Documented + 詳細 JavaDoc
- 組合註解:Spring
@RestController = @Controller + @ResponseBody
- 上一篇文章: Git 常用命令速查手冊:分支管理、遠程追蹤與撤銷操作
- 下一篇文章: Java 敏感詞過濾 DFA 算法實戰:Trie 樹構建、多模式匹配與替換策略
Copyright ©
程式碼之家 All Rights Reserved