一文詳解Java中的注解(Annotation)
在Java中,注解(Annotation)引入始于Java5,用來(lái)描述Java代碼的元信息,通常情況下注解不會(huì)直接影響代碼的執(zhí)行,盡管有些注解可以用來(lái)做到影響代碼執(zhí)行。
注解可以做什么
Java中的注解通常扮演以下角色
- 編譯器指令
- 構(gòu)建時(shí)指令
- 運(yùn)行時(shí)指令
其中
- Java內(nèi)置了三種編譯器指令,本文后面部分會(huì)重點(diǎn)介紹
- Java注解可以應(yīng)用在構(gòu)建時(shí),即當(dāng)你構(gòu)建你的項(xiàng)目時(shí)。構(gòu)建過(guò)程包括生成源碼,編譯源碼,生成xml文件,打包編譯的源碼和文件到JAR包等。軟件的構(gòu)建通常使用諸如Apache Ant和Maven這種工具自動(dòng)完成。這些構(gòu)建工具會(huì)依照特定的注解掃描Java代碼,然后根據(jù)這些注解生成源碼或文件。
- 通常情況下,注解并不會(huì)出現(xiàn)在編譯后的代碼中,但是如果想要出現(xiàn)也是可以的。Java支持運(yùn)行時(shí)的注解,使用Java的反射我們可以訪問(wèn)到這些注解,運(yùn)行時(shí)的注解的目的通常是提供給程序和第三方API一些指令。
注解基礎(chǔ)
一個(gè)簡(jiǎn)單的Java注解類似與@Entity。其中@的意思是告訴編譯器這是一個(gè)注解。而Entity則是注解的名字。通常在文件中,寫法如下
public @interface Entity { }
注解元素
Java注解可以使用元素來(lái)進(jìn)行設(shè)置一些值,注解中的元素類似于屬性或者參數(shù)。定義包含元素的注解示例代碼
public @interface Entity { String tableName(); }
使用包含元素的注解示例代碼
@Entity(tableName = "vehicles")
上述注解的元素名稱為tableName,設(shè)置的值為vehicles。沒(méi)有元素的注解不需要使用括號(hào)。
如果注解包含多個(gè)元素,使用方法如下
@Entity(tableName = "vehicles", primaryKey = "id")
如果注解只有一個(gè)元素,通常我們的寫法是這樣的
@InsertNew(value = "yes")
但是這種情況下,當(dāng)且僅當(dāng)元素名為value,我們也可以簡(jiǎn)寫,即不需要填寫元素名value,效果如下
@InsertNew("yes")
注解使用
注解可以用來(lái)修飾代碼中的這些元素
- 類
- 接口
- 方法
- 方法參數(shù)
- 屬性
- 局部變量
一個(gè)完整的使用示例如下
@Entity
public class Vehicle {
@Persistent
protected String vehicleName = null;
@Getter
public String getVehicleName() {
return this.vehicleName;
}
public void setVehicleName(@Optional vehicleName) {
this.vehicleName = vehicleName;
}
public List addVehicleNameToList(List names) {
@Optional
List localNames = names;
if(localNames == null) {
localNames = new ArrayList();
}
localNames.add(getVehicleName());
return localNames;
}
}
內(nèi)置的Java注解
Java中有三種內(nèi)置注解,這些注解用來(lái)為編譯器提供指令。它們是
- @Deprecated
- @Override
- @SuppressWarnings
@Deprecated
- 可以用來(lái)標(biāo)記類,方法,屬性。
- 如果上述三種元素不再使用,使用@Deprecated注解
- 如果代碼使用了@Deprecated注解的類,方法或?qū)傩?,編譯器會(huì)進(jìn)行警告。
@Deprecated使用很簡(jiǎn)單,如下為注解一個(gè)棄用的類。
@Deprecated
public class MyComponent {
}
當(dāng)我們使用@Deprecated注解后,建議配合使用對(duì)應(yīng)的@deprecated JavaDoc符號(hào),并解釋說(shuō)明為什么這個(gè)類,方法或?qū)傩员粭売?,已?jīng)替代方案是什么。
@Deprecated
/**
@deprecated This class is full of bugs. Use MyNewComponent instead.
*/
public class MyComponent {
}
@Override
@Override注解用來(lái)修飾對(duì)父類進(jìn)行重寫的方法。如果一個(gè)并非重寫父類的方法使用這個(gè)注解,編譯器將提示錯(cuò)誤。
實(shí)際上在子類中重寫父類或接口的方法,@Overide并不是必須的。但是還是建議使用這個(gè)注解,在某些情況下,假設(shè)你修改了父類的方法的名字,那么之前重寫的子類方法將不再屬于重寫,如果沒(méi)有@Overide,你將不會(huì)察覺(jué)到這個(gè)子類的方法。有了這個(gè)注解修飾,編譯器則會(huì)提示你這些信息。
使用Override注解的例子
public class MySuperClass {
public void doTheThing() {
System.out.println("Do the thing");
}
}
public class MySubClass extends MySuperClass{
@Override
public void doTheThing() {
System.out.println("Do it differently");
}
}@SuppressWarnings
- @SuppressWarnings用來(lái)抑制編譯器生成警告信息。
- 可以修飾的元素為類,方法,方法參數(shù),屬性,局部變量
使用場(chǎng)景:當(dāng)我們一個(gè)方法調(diào)用了棄用的方法或者進(jìn)行不安全的類型轉(zhuǎn)換,編譯器會(huì)生成警告。我們可以為這個(gè)方法增加@SuppressWarnings注解,來(lái)抑制編譯器生成警告。
注意:使用@SuppressWarnings注解,采用就近原則,比如一個(gè)方法出現(xiàn)警告,我們盡量使用@SuppressWarnings注解這個(gè)方法,而不是注解方法所在的類。雖然兩個(gè)都能抑制編譯器生成警告,但是范圍越小越好,因?yàn)榉秶罅?,不利于我們發(fā)現(xiàn)該類下其他方法的警告信息。
使用示例
@SuppressWarnings public void methodWithWarning() {
}
創(chuàng)建自己的注解
在Java中,我們可以創(chuàng)建自己的注解,注解和類,接口文件一樣定義在自己的文件里面。如下
@interface MyAnnotation {
String value();
String name();
int age();
String[] newNames();
}
上述代碼定義了一個(gè)叫做MyAnnotation的注解,它有4個(gè)元素。再次強(qiáng)調(diào)一下,@interface這個(gè)關(guān)鍵字用來(lái)告訴java編譯器這是一個(gè)注解。
仔細(xì)一看,你會(huì)發(fā)現(xiàn),注解元素的定義很類似于接口的方法。這些元素有類型和名稱。這些類型可以是
- 原始數(shù)據(jù)類型
- String
- Class
- annotation
- 枚舉
- 一維數(shù)組
如下為應(yīng)用自定義的注解
@MyAnnotation(
value="123",
name="Jakob",
age=37,
newNames={"Jenkov", "Peterson"}
)
public class MyClass {
}
注意,我們需要為所有的注解元素設(shè)置值,一個(gè)都不能少。
注解元素默認(rèn)值
對(duì)于注解中的元素,我們可以為其設(shè)置默認(rèn)值,使用方法為
@interface MyAnnotation {
String value() default "";
String name();
int age();
String[] newNames();
}
上述代碼,我們?cè)O(shè)置了value元素的默認(rèn)值為空字符串。當(dāng)我們?cè)谑褂脮r(shí),可以不設(shè)置value的值,即讓value使用空字符串默認(rèn)值。 使用示例代碼
@MyAnnotation(
name="Jakob",
age=37,
newNames={"Jenkov", "Peterson"}
)
public class MyClass {
}
@Retention
@Retention是用來(lái)修飾注解的注解,使用這個(gè)注解,我們可以做到
- 控制注解是否寫入class文件
- 控制class文件中的注解是否在運(yùn)行時(shí)可見(jiàn)
控制很簡(jiǎn)單,使用使用以下三種策略之一即可。
- RetentionPolicy.SOURCE 表明注解僅存在源碼之中,不存在.class文件,更不能運(yùn)行時(shí)可見(jiàn)。常見(jiàn)的注解為@Override, @SuppressWarnings。
- RetentionPolicy.CLASS 這是默認(rèn)的注解保留策略。這種策略下,注解將存在與.class文件,但是不能被運(yùn)行時(shí)訪問(wèn)。通常這種注解策略用來(lái)處于一些字節(jié)碼級(jí)別的操作。
- RetentionPolicy.RUNTIME 這種策略下可以被運(yùn)行時(shí)訪問(wèn)到。通常情況下,我們都會(huì)結(jié)合反射來(lái)做一些事情。
@Retention的使用示例
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
@interface MyAnnotation {
String value() default "";
}
@Target
使用@Target注解,我們可以設(shè)定自定義注解可以修飾哪些java元素。簡(jiǎn)單示例
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target({ElementType.METHOD})
public @interface MyAnnotation {
String value();
}
上述的代碼說(shuō)明MyAnnotation注解只能修飾方法。
@Target可以選擇的參數(shù)值有如下這些
- ElementType.ANNOTATION_TYPE(注:修飾注解)
- ElementType.CONSTRUCTOR
- ElementType.FIELD
- ElementType.LOCAL_VARIABLE
- ElementType.METHOD
- ElementType.PACKAGE
- ElementType.PARAMETER
- ElementType.TYPE(注:任何類型,即上面的的類型都可以修飾)
@Inherited
如果你想讓一個(gè)類和它的子類都包含某個(gè)注解,就可以使用@Inherited來(lái)修飾這個(gè)注解。
java.lang.annotation.Inherited
@Inherited
public @interface MyAnnotation {
}
@MyAnnotation
public class MySuperClass { ... }
public class MySubClass extends MySuperClass { ... }
上述代碼的大致意思是
- 使用@Inherited修飾注解MyAnnotation
- 使用MyAnnotation注解MySuperClass
- 實(shí)現(xiàn)一個(gè)類MySubclass繼承自MySuperClass
通過(guò)以上幾步,MySubClass也擁有了MyAnnotation注解。
關(guān)于Java中的注解,一些基本的概念就是這些。
總結(jié)
到此這篇關(guān)于Java中注解(Annotation)的文章就介紹到這了,更多相關(guān)Java注解使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
為什么JDK8中HashMap依然會(huì)死循環(huán)
這篇文章主要介紹了為什么JDK8中HashMap依然會(huì)死循環(huán),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
SpringBoot整合JWT框架,解決Token跨域驗(yàn)證問(wèn)題
Json web token (JWT), 是為了在網(wǎng)絡(luò)應(yīng)用環(huán)境間傳遞聲明而執(zhí)行的一種基于JSON的開放標(biāo)準(zhǔn)((RFC 7519).定義了一種簡(jiǎn)潔的,自包含的方法用于通信雙方之間以JSON對(duì)象的形式安全的傳遞信息。2021-06-06
Java之while與do-while循環(huán)的用法詳解
在上一篇文章中,給大家講解了循環(huán)的概念,并重點(diǎn)給大家講解了for循環(huán)的使用。但在Java中,除了for循環(huán)之外,還有while、do-while、foreach等循環(huán)形式。這篇文章給大家講解while循環(huán)的使用2023-05-05
Java+MySQL實(shí)現(xiàn)設(shè)計(jì)優(yōu)惠券系統(tǒng)
這篇文章主要介紹了Java+MySQL實(shí)現(xiàn)設(shè)計(jì)優(yōu)惠券系統(tǒng),文章基于Java與MySQL的相關(guān)資料展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-05-05
java實(shí)現(xiàn)爬蟲爬網(wǎng)站圖片的實(shí)例代碼
這篇文章主要介紹了java實(shí)現(xiàn)爬蟲爬網(wǎng)站圖片的實(shí)例代碼,需要的朋友可以參考下2018-06-06
淺談Spring如何解決循環(huán)依賴的問(wèn)題
這篇文章主要介紹了淺談Spring如何解決循環(huán)依賴的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09
Spring Security賬戶與密碼驗(yàn)證實(shí)現(xiàn)過(guò)程
這篇文章主要介紹了Spring Security賬戶與密碼驗(yàn)證實(shí)現(xiàn)過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2023-03-03

