Java注解(Annotations)的定義和使用詳解
Java 注解(Annotations)是 Java 5 引入的一種元數(shù)據(jù)(Metadata),它提供了一種在源代碼中嵌入補充信息的方式,這些信息可以被編譯器、JVM 或其他工具在編譯時、運行時進行處理。
注解本身不會直接影響程序的執(zhí)行,但可以用來指導編譯器、JVM 或其他工具的行為,從而實現(xiàn)各種功能。
一、 注解的定義 (Annotation Definition)
什么是元數(shù)據(jù) (Metadata)?
- 元數(shù)據(jù)是描述數(shù)據(jù)的數(shù)據(jù)。 在 Java 中,元數(shù)據(jù)是指描述程序代碼的數(shù)據(jù),例如類、方法、字段等的屬性信息。
- 注解就是一種元數(shù)據(jù),它可以用來描述類、方法、字段、參數(shù)、局部變量等程序元素。
注解的語法
@Retention(RetentionPolicy.RUNTIME) // 元注解,指定注解的保留策略
@Target({ElementType.METHOD, ElementType.TYPE}) // 元注解,指定注解可以應用的程序元素類型
public @interface MyAnnotation { // 定義一個注解
// 注解成員 (Annotation Members)
String name() default "Default Name"; // 默認值
int value(); // 必須賦值
Class<?> type() default void.class; //類型
}@interface關鍵字: 用于定義一個注解。- 注解名 (Annotation Name): 遵循 PascalCase 命名規(guī)范(每個單詞首字母大寫),例如
Override,Deprecated,WebServlet。 - 注解成員 (Annotation Members):
- 類似于接口中的方法聲明,但沒有方法體。
- 可以有默認值 (使用
default關鍵字指定)。 - 如果沒有默認值,則在使用注解時必須顯式賦值。
- 成員的類型可以是原始類型、
String、Class、枚舉類型、注解類型或這些類型的數(shù)組。 - 注解成員實際上類似于接口中的方法,這意味著它們可以有訪問修飾符,但通常省略 (默認是
public)。 - 注解成員后面要跟一對小括號,即使沒有參數(shù)。
二、元注解 (Meta-Annotations)
元注解是用于修飾注解的注解,用于指定注解的特性。
1.@Retention:
作用: 指定注解的保留策略 (Retention Policy),即注解在哪個階段可用。
RetentionPolicy 枚舉:
RetentionPolicy.SOURCE: 注解僅保留在源代碼中,在編譯時被丟棄。 例如,@Override注解。RetentionPolicy.CLASS: 注解保留在 class 文件中,但在運行時會被 JVM 丟棄。RetentionPolicy.RUNTIME: 注解保留在 class 文件中,并且在運行時可以通過反射 API 獲取。 這是最常用的保留策略,可以實現(xiàn)各種動態(tài)功能。
示例:
@Retention(RetentionPolicy.RUNTIME) // 指定注解在運行時可用
public @interface MyAnnotation {
// ...
}2.@Target:
作用: 指定注解可以應用的程序元素類型 (Target Element)。
ElementType 枚舉:
ElementType.TYPE: 可以應用于類、接口、枚舉、注解。ElementType.FIELD: 可以應用于字段。ElementType.METHOD: 可以應用于方法。ElementType.PARAMETER: 可以應用于方法參數(shù)。ElementType.CONSTRUCTOR: 可以應用于構造方法。ElementType.LOCAL_VARIABLE: 可以應用于局部變量。ElementType.ANNOTATION_TYPE: 可以應用于注解。ElementType.PACKAGE: 可以應用于包。ElementType.TYPE_PARAMETER: 類型參數(shù),since 1.8ElementType.TYPE_USE: 使用類型的任何地方, since 1.8
示例:
@Target({ElementType.METHOD, ElementType.TYPE}) // 指定注解可以應用于方法和類
public @interface MyAnnotation {
// ...
}1.@Documented:
作用: 指定該注解應該包含在 Javadoc 文檔中。
示例:
@Documented // 指定該注解應該包含在 Javadoc 文檔中
public @interface MyAnnotation {
// ...
}2.@Inherited:
作用: 指定該注解可以被子類繼承。
示例:
@Inherited // 指定該注解可以被子類繼承
public @interface MyAnnotation {
// ...
}3.@Repeatable (Java 8+):
作用: 指定該注解可以在同一個程序元素上重復使用。
示例:
@Repeatable(Authorities.class)
public @interface Authority {
String role();
}
public @interface Authorities {
Authority[] value();
}
@Authority(role="Admin")
@Authority(role="Editor")
public class MyClass {
// ...
}三、內(nèi)置注解 (Built-in Annotations)
Java 提供了一些內(nèi)置注解,可以直接使用:
1.@Override:
作用: 用于標記一個方法是重寫 (Override) 了父類的方法。
用途:
- 幫助編譯器檢查是否正確地重寫了方法。 如果方法簽名與父類方法不匹配,編譯器會報錯。
- 提高代碼可讀性,明確表明該方法是重寫了父類的方法。
示例:
class Animal {
void eat() {
System.out.println("Animal is eating.");
}
}
class Dog extends Animal {
@Override // 標記該方法重寫了父類的 eat() 方法
void eat() {
System.out.println("Dog is eating.");
}
}2.@Deprecated:
作用: 用于標記一個類、方法或字段已過時 (Deprecated),不建議使用。
用途:
- 提醒開發(fā)者該類、方法或字段已經(jīng)不推薦使用,可能會在將來的版本中被移除。
- 可以提供替代方案的說明。
示例:
@Deprecated // 標記該方法已過時
public void oldMethod() {
// ...
}
/**
* @deprecated Use {@link #newMethod()} instead.
*/
@Deprecated
public void oldMethodWithComment(){
//...
}
public void newMethod() {
// ...
}3.@SuppressWarnings:
作用: 用于抑制編譯器發(fā)出的警告。
用途:
- 在某些情況下,編譯器可能會發(fā)出一些不必要的警告,可以使用
@SuppressWarnings注解來抑制這些警告。
取值:
all: 抑制所有警告。boxing: 抑制與自動裝箱/拆箱相關的警告。deprecation: 抑制與使用了@Deprecated標記的類、方法或字段相關的警告。unchecked: 抑制與未檢查的類型轉換相關的警告(例如,在使用原始類型時)。unused: 抑制與未使用的變量相關的警告。resource: 抑制與資源未關閉相關的警告。- 等等 (具體取決于編譯器)。
示例:
@SuppressWarnings("unchecked") // 抑制類型轉換警告
List list = new ArrayList();
list.add("Hello");
String s = (String) list.get(0); // 編譯器會發(fā)出 unchecked 類型轉換警告四、自定義注解 (Custom Annotations)
除了內(nèi)置注解,你還可以根據(jù)自己的需求創(chuàng)建自定義注解。
定義注解:
- 使用
@interface關鍵字定義注解。 - 指定元注解 (
@Retention,@Target等)。 - 定義注解成員。
使用注解:
- 在程序元素(類、方法、字段等)上使用自定義注解,并為注解成員賦值(如果需要)。
處理注解 (Annotation Processing):
- 編譯時處理: 可以使用注解處理器 (Annotation Processor) 在編譯時處理注解,生成代碼或配置文件。 例如,Lombok 使用注解處理器自動生成 getter/setter 方法。
- 運行時處理: 可以使用反射 API 在運行時獲取注解信息,并根據(jù)注解信息執(zhí)行相應的邏輯。
五、使用場景 (Annotation Usage Scenarios)
注解在 Java 中有著廣泛的應用,主要包括以下場景:
編譯時檢查:
- 使用
@Override注解進行方法重寫檢查。 - 使用
@SuppressWarnings注解抑制編譯器警告。
代碼生成:
- Lombok 使用注解處理器自動生成 getter/setter 方法、構造方法、
equals()/hashCode()方法等,簡化代碼編寫。 - JPA 使用注解來映射類和數(shù)據(jù)庫表,生成 SQL 語句。
- Spring MVC 使用注解來映射請求 URL 和處理方法。
配置:
- Spring 使用注解來配置 Bean、依賴注入、事務管理、AOP 等。
- JAX-RS 使用注解來定義 RESTful Web 服務。
運行時行為修改:
- 單元測試框架 (例如 JUnit, TestNG) 使用注解來標記測試方法。
- 安全框架 (例如 Spring Security) 使用注解來進行權限控制。
- 序列化框架 (例如 Jackson, Gson) 使用注解來控制序列化和反序列化過程。
六、代碼示例 (自定義注解)
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
@Retention(RetentionPolicy.RUNTIME) // 指定注解在運行時可用
@Target(ElementType.METHOD) // 指定注解可以應用于方法
public @interface MyAnnotation { // 定義一個自定義注解
String name() default "Default Name"; // 成員變量,默認值Default Name
int value(); // 成員變量
}
class MyClass {
@MyAnnotation(name = "My Method", value = 100) // 使用注解并賦值
public void myMethod() {
System.out.println("My method is called.");
}
}
public class AnnotationExample {
public static void main(String[] args) throws Exception {
Class<?> clazz = MyClass.class;
Method method = clazz.getMethod("myMethod");
if (method.isAnnotationPresent(MyAnnotation.class)) { // 判斷方法是否使用了 MyAnnotation 注解
MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); // 獲取注解對象
System.out.println("Annotation name: " + annotation.name()); // 獲取 name 成員的值
System.out.println("Annotation value: " + annotation.value()); // 獲取 value 成員的值
}
}
}總結
Java 注解是一種強大的元數(shù)據(jù)機制,它可以在代碼中嵌入補充信息,并在編譯時或運行時被處理。 理解注解的定義、元注解、內(nèi)置注解、自定義注解以及使用場景,可以幫助你編寫更簡潔、更靈活、更易于維護的 Java 代碼。 掌握注解,能讓你更深入地理解各種框架和庫的運作方式,并能夠自定義 Spring Boot Starter等功能.
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
SpringBoot進行Web開發(fā)的實現(xiàn)
Spring?Boot讓我們可以快速構建項目并運行web應用,大大簡化了Spring的復雜配置,本文主要介紹了SpringBoot進行Web開發(fā)的實現(xiàn),感興趣的可以了解一下2023-10-10
Spring Boot項目集成UidGenerato的方法步驟
這篇文章主要介紹了Spring Boot項目集成UidGenerato的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-12-12
SpringBoot前后端分離跨域問題:狀態(tài)碼403拒絕訪問解決辦法
這篇文章主要給大家介紹了關于SpringBoot前后端分離跨域問題:狀態(tài)碼403拒絕訪問的解決辦法,403是被服務器拒絕了,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-01-01

