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}) // 元注解,指定注解可以應(yīng)用的程序元素類型 public @interface MyAnnotation { // 定義一個注解 // 注解成員 (Annotation Members) String name() default "Default Name"; // 默認值 int value(); // 必須賦值 Class<?> type() default void.class; //類型 }
@interface
關(guān)鍵字: 用于定義一個注解。- 注解名 (Annotation Name): 遵循 PascalCase 命名規(guī)范(每個單詞首字母大寫),例如
Override
,Deprecated
,WebServlet
。 - 注解成員 (Annotation Members):
- 類似于接口中的方法聲明,但沒有方法體。
- 可以有默認值 (使用
default
關(guān)鍵字指定)。 - 如果沒有默認值,則在使用注解時必須顯式賦值。
- 成員的類型可以是原始類型、
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
:
作用: 指定注解可以應(yīng)用的程序元素類型 (Target Element)。
ElementType
枚舉:
ElementType.TYPE
: 可以應(yīng)用于類、接口、枚舉、注解。ElementType.FIELD
: 可以應(yīng)用于字段。ElementType.METHOD
: 可以應(yīng)用于方法。ElementType.PARAMETER
: 可以應(yīng)用于方法參數(shù)。ElementType.CONSTRUCTOR
: 可以應(yīng)用于構(gòu)造方法。ElementType.LOCAL_VARIABLE
: 可以應(yīng)用于局部變量。ElementType.ANNOTATION_TYPE
: 可以應(yīng)用于注解。ElementType.PACKAGE
: 可以應(yīng)用于包。ElementType.TYPE_PARAMETER
: 類型參數(shù),since 1.8ElementType.TYPE_USE
: 使用類型的任何地方, since 1.8
示例:
@Target({ElementType.METHOD, ElementType.TYPE}) // 指定注解可以應(yīng)用于方法和類 public @interface MyAnnotation { // ... }
1.@Documented
:
作用: 指定該注解應(yīng)該包含在 Javadoc 文檔中。
示例:
@Documented // 指定該注解應(yīng)該包含在 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
: 抑制與自動裝箱/拆箱相關(guān)的警告。deprecation
: 抑制與使用了@Deprecated
標記的類、方法或字段相關(guān)的警告。unchecked
: 抑制與未檢查的類型轉(zhuǎn)換相關(guān)的警告(例如,在使用原始類型時)。unused
: 抑制與未使用的變量相關(guān)的警告。resource
: 抑制與資源未關(guān)閉相關(guān)的警告。- 等等 (具體取決于編譯器)。
示例:
@SuppressWarnings("unchecked") // 抑制類型轉(zhuǎn)換警告 List list = new ArrayList(); list.add("Hello"); String s = (String) list.get(0); // 編譯器會發(fā)出 unchecked 類型轉(zhuǎn)換警告
四、自定義注解 (Custom Annotations)
除了內(nèi)置注解,你還可以根據(jù)自己的需求創(chuàng)建自定義注解。
定義注解:
- 使用
@interface
關(guān)鍵字定義注解。 - 指定元注解 (
@Retention
,@Target
等)。 - 定義注解成員。
使用注解:
- 在程序元素(類、方法、字段等)上使用自定義注解,并為注解成員賦值(如果需要)。
處理注解 (Annotation Processing):
- 編譯時處理: 可以使用注解處理器 (Annotation Processor) 在編譯時處理注解,生成代碼或配置文件。 例如,Lombok 使用注解處理器自動生成 getter/setter 方法。
- 運行時處理: 可以使用反射 API 在運行時獲取注解信息,并根據(jù)注解信息執(zhí)行相應(yīng)的邏輯。
五、使用場景 (Annotation Usage Scenarios)
注解在 Java 中有著廣泛的應(yīng)用,主要包括以下場景:
編譯時檢查:
- 使用
@Override
注解進行方法重寫檢查。 - 使用
@SuppressWarnings
注解抑制編譯器警告。
代碼生成:
- Lombok 使用注解處理器自動生成 getter/setter 方法、構(gòu)造方法、
equals()
/hashCode()
方法等,簡化代碼編寫。 - JPA 使用注解來映射類和數(shù)據(jù)庫表,生成 SQL 語句。
- Spring MVC 使用注解來映射請求 URL 和處理方法。
配置:
- Spring 使用注解來配置 Bean、依賴注入、事務(wù)管理、AOP 等。
- JAX-RS 使用注解來定義 RESTful Web 服務(wù)。
運行時行為修改:
- 單元測試框架 (例如 JUnit, TestNG) 使用注解來標記測試方法。
- 安全框架 (例如 Spring Security) 使用注解來進行權(quán)限控制。
- 序列化框架 (例如 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) // 指定注解可以應(yīng)用于方法 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 成員的值 } } }
總結(jié)
Java 注解是一種強大的元數(shù)據(jù)機制,它可以在代碼中嵌入補充信息,并在編譯時或運行時被處理。 理解注解的定義、元注解、內(nèi)置注解、自定義注解以及使用場景,可以幫助你編寫更簡潔、更靈活、更易于維護的 Java 代碼。 掌握注解,能讓你更深入地理解各種框架和庫的運作方式,并能夠自定義 Spring Boot Starter等功能.
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot進行Web開發(fā)的實現(xiàn)
Spring?Boot讓我們可以快速構(gòu)建項目并運行web應(yīng)用,大大簡化了Spring的復雜配置,本文主要介紹了SpringBoot進行Web開發(fā)的實現(xiàn),感興趣的可以了解一下2023-10-10深度解析Spring AI請求與響應(yīng)機制的核心邏輯
我們在前面的兩個章節(jié)中基本上對Spring Boot 3版本的新變化進行了全面的回顧,以確保在接下來研究Spring AI時能夠避免任何潛在的問題,本文給大家介紹Spring AI請求與響應(yīng)機制的核心邏輯,感興趣的朋友跟隨小編一起看看吧2024-11-11Spring Boot項目集成UidGenerato的方法步驟
這篇文章主要介紹了Spring Boot項目集成UidGenerato的方法步驟,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-12-12SpringBoot前后端分離跨域問題:狀態(tài)碼403拒絕訪問解決辦法
這篇文章主要給大家介紹了關(guān)于SpringBoot前后端分離跨域問題:狀態(tài)碼403拒絕訪問的解決辦法,403是被服務(wù)器拒絕了,文中通過代碼介紹的非常詳細,需要的朋友可以參考下2024-01-01使用JAXBContext 設(shè)置xml節(jié)點屬性
這篇文章主要介紹了使用JAXBContext 設(shè)置xml節(jié)點屬性的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08