Java注解(Annotations)的定義和使用詳解
Java 注解(Annotations)是 Java 5 引入的一種元數(shù)據(jù)(Metadata),它提供了一種在源代碼中嵌入補(bǔ)充信息的方式,這些信息可以被編譯器、JVM 或其他工具在編譯時(shí)、運(yùn)行時(shí)進(jìn)行處理。
注解本身不會(huì)直接影響程序的執(zhí)行,但可以用來(lái)指導(dǎo)編譯器、JVM 或其他工具的行為,從而實(shí)現(xiàn)各種功能。
一、 注解的定義 (Annotation Definition)
什么是元數(shù)據(jù) (Metadata)?
- 元數(shù)據(jù)是描述數(shù)據(jù)的數(shù)據(jù)。 在 Java 中,元數(shù)據(jù)是指描述程序代碼的數(shù)據(jù),例如類、方法、字段等的屬性信息。
- 注解就是一種元數(shù)據(jù),它可以用來(lái)描述類、方法、字段、參數(shù)、局部變量等程序元素。
注解的語(yǔ)法
@Retention(RetentionPolicy.RUNTIME) // 元注解,指定注解的保留策略
@Target({ElementType.METHOD, ElementType.TYPE}) // 元注解,指定注解可以應(yīng)用的程序元素類型
public @interface MyAnnotation { // 定義一個(gè)注解
// 注解成員 (Annotation Members)
String name() default "Default Name"; // 默認(rèn)值
int value(); // 必須賦值
Class<?> type() default void.class; //類型
}@interface關(guān)鍵字: 用于定義一個(gè)注解。- 注解名 (Annotation Name): 遵循 PascalCase 命名規(guī)范(每個(gè)單詞首字母大寫),例如
Override,Deprecated,WebServlet。 - 注解成員 (Annotation Members):
- 類似于接口中的方法聲明,但沒(méi)有方法體。
- 可以有默認(rèn)值 (使用
default關(guān)鍵字指定)。 - 如果沒(méi)有默認(rèn)值,則在使用注解時(shí)必須顯式賦值。
- 成員的類型可以是原始類型、
String、Class、枚舉類型、注解類型或這些類型的數(shù)組。 - 注解成員實(shí)際上類似于接口中的方法,這意味著它們可以有訪問(wèn)修飾符,但通常省略 (默認(rèn)是
public)。 - 注解成員后面要跟一對(duì)小括號(hào),即使沒(méi)有參數(shù)。
二、元注解 (Meta-Annotations)
元注解是用于修飾注解的注解,用于指定注解的特性。
1.@Retention:
作用: 指定注解的保留策略 (Retention Policy),即注解在哪個(gè)階段可用。
RetentionPolicy 枚舉:
RetentionPolicy.SOURCE: 注解僅保留在源代碼中,在編譯時(shí)被丟棄。 例如,@Override注解。RetentionPolicy.CLASS: 注解保留在 class 文件中,但在運(yùn)行時(shí)會(huì)被 JVM 丟棄。RetentionPolicy.RUNTIME: 注解保留在 class 文件中,并且在運(yùn)行時(shí)可以通過(guò)反射 API 獲取。 這是最常用的保留策略,可以實(shí)現(xiàn)各種動(dòng)態(tài)功能。
示例:
@Retention(RetentionPolicy.RUNTIME) // 指定注解在運(yùn)行時(shí)可用
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+):
作用: 指定該注解可以在同一個(gè)程序元素上重復(fù)使用。
示例:
@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:
作用: 用于標(biāo)記一個(gè)方法是重寫 (Override) 了父類的方法。
用途:
- 幫助編譯器檢查是否正確地重寫了方法。 如果方法簽名與父類方法不匹配,編譯器會(huì)報(bào)錯(cuò)。
- 提高代碼可讀性,明確表明該方法是重寫了父類的方法。
示例:
class Animal {
void eat() {
System.out.println("Animal is eating.");
}
}
class Dog extends Animal {
@Override // 標(biāo)記該方法重寫了父類的 eat() 方法
void eat() {
System.out.println("Dog is eating.");
}
}2.@Deprecated:
作用: 用于標(biāo)記一個(gè)類、方法或字段已過(guò)時(shí) (Deprecated),不建議使用。
用途:
- 提醒開(kāi)發(fā)者該類、方法或字段已經(jīng)不推薦使用,可能會(huì)在將來(lái)的版本中被移除。
- 可以提供替代方案的說(shuō)明。
示例:
@Deprecated // 標(biāo)記該方法已過(guò)時(shí)
public void oldMethod() {
// ...
}
/**
* @deprecated Use {@link #newMethod()} instead.
*/
@Deprecated
public void oldMethodWithComment(){
//...
}
public void newMethod() {
// ...
}3.@SuppressWarnings:
作用: 用于抑制編譯器發(fā)出的警告。
用途:
- 在某些情況下,編譯器可能會(huì)發(fā)出一些不必要的警告,可以使用
@SuppressWarnings注解來(lái)抑制這些警告。
取值:
all: 抑制所有警告。boxing: 抑制與自動(dòng)裝箱/拆箱相關(guān)的警告。deprecation: 抑制與使用了@Deprecated標(biāo)記的類、方法或字段相關(guān)的警告。unchecked: 抑制與未檢查的類型轉(zhuǎn)換相關(guān)的警告(例如,在使用原始類型時(shí))。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); // 編譯器會(huì)發(fā)出 unchecked 類型轉(zhuǎn)換警告四、自定義注解 (Custom Annotations)
除了內(nèi)置注解,你還可以根據(jù)自己的需求創(chuàng)建自定義注解。
定義注解:
- 使用
@interface關(guān)鍵字定義注解。 - 指定元注解 (
@Retention,@Target等)。 - 定義注解成員。
使用注解:
- 在程序元素(類、方法、字段等)上使用自定義注解,并為注解成員賦值(如果需要)。
處理注解 (Annotation Processing):
- 編譯時(shí)處理: 可以使用注解處理器 (Annotation Processor) 在編譯時(shí)處理注解,生成代碼或配置文件。 例如,Lombok 使用注解處理器自動(dòng)生成 getter/setter 方法。
- 運(yùn)行時(shí)處理: 可以使用反射 API 在運(yùn)行時(shí)獲取注解信息,并根據(jù)注解信息執(zhí)行相應(yīng)的邏輯。
五、使用場(chǎng)景 (Annotation Usage Scenarios)
注解在 Java 中有著廣泛的應(yīng)用,主要包括以下場(chǎng)景:
編譯時(shí)檢查:
- 使用
@Override注解進(jìn)行方法重寫檢查。 - 使用
@SuppressWarnings注解抑制編譯器警告。
代碼生成:
- Lombok 使用注解處理器自動(dòng)生成 getter/setter 方法、構(gòu)造方法、
equals()/hashCode()方法等,簡(jiǎn)化代碼編寫。 - JPA 使用注解來(lái)映射類和數(shù)據(jù)庫(kù)表,生成 SQL 語(yǔ)句。
- Spring MVC 使用注解來(lái)映射請(qǐng)求 URL 和處理方法。
配置:
- Spring 使用注解來(lái)配置 Bean、依賴注入、事務(wù)管理、AOP 等。
- JAX-RS 使用注解來(lái)定義 RESTful Web 服務(wù)。
運(yùn)行時(shí)行為修改:
- 單元測(cè)試框架 (例如 JUnit, TestNG) 使用注解來(lái)標(biāo)記測(cè)試方法。
- 安全框架 (例如 Spring Security) 使用注解來(lái)進(jìn)行權(quán)限控制。
- 序列化框架 (例如 Jackson, Gson) 使用注解來(lái)控制序列化和反序列化過(guò)程。
六、代碼示例 (自定義注解)
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) // 指定注解在運(yùn)行時(shí)可用
@Target(ElementType.METHOD) // 指定注解可以應(yīng)用于方法
public @interface MyAnnotation { // 定義一個(gè)自定義注解
String name() default "Default Name"; // 成員變量,默認(rèn)值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); // 獲取注解對(duì)象
System.out.println("Annotation name: " + annotation.name()); // 獲取 name 成員的值
System.out.println("Annotation value: " + annotation.value()); // 獲取 value 成員的值
}
}
}總結(jié)
Java 注解是一種強(qiáng)大的元數(shù)據(jù)機(jī)制,它可以在代碼中嵌入補(bǔ)充信息,并在編譯時(shí)或運(yùn)行時(shí)被處理。 理解注解的定義、元注解、內(nèi)置注解、自定義注解以及使用場(chǎng)景,可以幫助你編寫更簡(jiǎn)潔、更靈活、更易于維護(hù)的 Java 代碼。 掌握注解,能讓你更深入地理解各種框架和庫(kù)的運(yùn)作方式,并能夠自定義 Spring Boot Starter等功能.
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot進(jìn)行Web開(kāi)發(fā)的實(shí)現(xiàn)
Spring?Boot讓我們可以快速構(gòu)建項(xiàng)目并運(yùn)行web應(yīng)用,大大簡(jiǎn)化了Spring的復(fù)雜配置,本文主要介紹了SpringBoot進(jìn)行Web開(kāi)發(fā)的實(shí)現(xiàn),感興趣的可以了解一下2023-10-10
深度解析Spring AI請(qǐng)求與響應(yīng)機(jī)制的核心邏輯
我們?cè)谇懊娴膬蓚€(gè)章節(jié)中基本上對(duì)Spring Boot 3版本的新變化進(jìn)行了全面的回顧,以確保在接下來(lái)研究Spring AI時(shí)能夠避免任何潛在的問(wèn)題,本文給大家介紹Spring AI請(qǐng)求與響應(yīng)機(jī)制的核心邏輯,感興趣的朋友跟隨小編一起看看吧2024-11-11
Spring Boot項(xiàng)目集成UidGenerato的方法步驟
這篇文章主要介紹了Spring Boot項(xiàng)目集成UidGenerato的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-12-12
SpringBoot前后端分離跨域問(wèn)題:狀態(tài)碼403拒絕訪問(wèn)解決辦法
這篇文章主要給大家介紹了關(guān)于SpringBoot前后端分離跨域問(wèn)題:狀態(tài)碼403拒絕訪問(wèn)的解決辦法,403是被服務(wù)器拒絕了,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-01-01
使用JAXBContext 設(shè)置xml節(jié)點(diǎn)屬性
這篇文章主要介紹了使用JAXBContext 設(shè)置xml節(jié)點(diǎn)屬性的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08

