[Java Again]之注解(Annotation)-基礎(chǔ)篇

本系列文章主要目的在于重新梳理 Java 基礎(chǔ)知識(shí),可能不會(huì)按照由淺入深的順序去寫。文章內(nèi)容主要參考《Core Java for the Impatient》一書。

注解相關(guān)的內(nèi)容打算分兩篇來寫:基礎(chǔ)篇和進(jìn)階篇,本文是基礎(chǔ)篇,主要涵蓋以下內(nèi)容:

  • 什么是注解
  • 注解的基本使用及分類
  • 標(biāo)準(zhǔn)注解與自定義注解

#0. 什么是注解

注解(Annotation)是 Java 在 1.5 版本中引入的新特性。它可以用來標(biāo)注源碼,并在編譯期或運(yùn)行時(shí)被注解處理器處理。如果你是一個(gè)優(yōu)雅的 Android Developer,那么你肯定對(duì) ButterKniferetrofit 等優(yōu)秀的三方庫非常熟悉。你沒看錯(cuò),它們都在使用注解讓代碼變的更優(yōu)雅,易于理解。下面就讓我們揭開注解神秘的面紗吧。

Are You Ready?

#1. 注解的基本使用及分類

在正式了解注解之前,我們先看一個(gè)例子:學(xué)過 Java 的同學(xué)應(yīng)該都知道,在自定義對(duì)象中,我們需要重寫 toString 方法以格式化打印該對(duì)象時(shí)的輸出。

public class Person {
    String name;
    int age;

    ...

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

相信你已經(jīng)注意到了 toString 方法上面的 @Override,它就是一個(gè)標(biāo)記在方法上的注解,用于表示該方法是對(duì)父類方法的重寫。

#1.1. 注解的基本使用

讓我們借著上面的例子來講一下注解的基本使用。如你所見,注解都是以 @ 開頭,后面緊跟一個(gè)標(biāo)準(zhǔn)或自定義注解類型(這里的 Override 是一個(gè)標(biāo)準(zhǔn)注解)。

注解可以聲明在源碼中的以下位置:

  • 類,枚舉,接口
  • 方法
  • 構(gòu)造器
  • 實(shí)例(全局)變量(包括枚舉常量)
  • 局部變量(包括 fortry 代碼塊中的變量)
  • 形式參數(shù)和 catch 中的參數(shù)
  • 類型參數(shù)
// 類注解
@Entity public class User{...}
// 變量注解
@SuppressWarnings("unchecked") List<User> users = ...;
public User getUser(@Param("id") String userId){...}
// 類型參數(shù)注解
public class Cache<@Immutable V> {...}
// 包注解
@GPL(version=“3”) 
package com.horstmann.corejava; 
import org.gnu.GPL; // 注意:導(dǎo)入語句在包定義下方

注解可以擁有一些被稱為元素的鍵值對(duì),以 JUnit 4 測(cè)試框架中的 @Test 注解為例:

@Test(timeout=2000)
public void testSample() {
    ...
}

此處的 timeout=2000表示該測(cè)試最長可執(zhí)行 2000 毫秒,超過 2000 毫秒沒有執(zhí)行完就會(huì)拋出異常:

java.lang.Exception: test timed out after 2000 milliseconds

如果注解中只有一個(gè)元素,且元素的鍵名為 value,則該元素的鍵可以省略,如上面的變量注解:

@SuppressWarnings("unchecked") List<User> users = ...;

元素的值可以是以下類型:

  • 原始類型
  • 字符串
  • Class 對(duì)象
  • 枚舉實(shí)例
  • 注解
  • 或以上類型的數(shù)組(不包括數(shù)組)

在同一個(gè)條目上可以有多個(gè)(相同的或不同的)注解。

@Test 
@BugReport(showStopper=true, reportedBy=“Joe”) 
public void checkRandomInsertions() { ... }

@BugReport(showStopper=true, reportedBy=“Joe”) 
@BugReport(reportedBy={“Harry”, “Carl”}) 
public void checkRandomInsertions() { ... }

#1.2. 注解的分類

根據(jù)注解保留的時(shí)期,可以將其分為三類:

  • 源碼期注解:只能保留在源碼文件中,不會(huì)被編譯到 .class 文件
  • 編譯期注解:只能被編譯器保留到 .class 文件中,不能被虛擬機(jī)保留到運(yùn)行時(shí)
  • 運(yùn)行時(shí)注解:能被虛擬機(jī)保留到運(yùn)行時(shí)

作用于注解類型上的注解被稱為元注解。

#2. 標(biāo)準(zhǔn)注解與自定義注解

Java 默認(rèn)實(shí)現(xiàn)了一些方便的注解類型供我們?cè)陂_發(fā)中使用,它還允許我們?cè)谛枰獣r(shí)創(chuàng)建自定義注解。

#2.1. Java 內(nèi)置標(biāo)準(zhǔn)注解

Java 的內(nèi)置注解的使用范圍及其作用可總結(jié)為下表:

摘自《Core Java for the Impatient》

需要注意的是最下面的五個(gè)注解,它們都是用在注解類型上的,是元注解。

#2.2. 自定義 Java 注解

與使用 class 聲明類相似,Java 使用 @interface 聲明一個(gè)注解類型:

public @interface BugReport { ... }

我們可以像給接口添加方法一樣為自定義注解添加元素:

public @interface BugReport {

    String desc();
    String[] reportBy() default {}; //添加默認(rèn)值,如果不指定,則使用該值
}

我們還可以給自定義注解指定保留時(shí)期和使用范圍:

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface BugReport {

    String desc();
    String[] reportBy() default {};
}

這樣,我們的 BugReport 將只能作用于類型級(jí)別上(不能在方法,字段上使用),而且指定其為編譯期注解。

下圖為 @Target 所有可用參數(shù)及其含義:

@Target 可用參數(shù)

@Retention 元注解只有三種選擇,分別對(duì)應(yīng)于上文的三個(gè)保留時(shí)期:

  • RetentionPolicy.SOURCE:源碼處理時(shí)可見,不會(huì)包含在 .class 文件中
  • RetentionPolicy.CLASS:默認(rèn)選擇,會(huì)包含在 .class 文件中,但不會(huì)被虛擬機(jī)加載
  • RetentionPolicy.RUNTIME:運(yùn)行時(shí)可見,可以通過反射 API 獲取

以上就是本文的全部?jī)?nèi)容,我們將會(huì)在進(jìn)階篇中講解更多關(guān)于注解的使用技巧,如果你對(duì)本文有任何建議,歡迎留言反饋。

#3. 延伸閱讀

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,825評(píng)論 6 546
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,814評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,980評(píng)論 0 384
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 64,064評(píng)論 1 319
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,779評(píng)論 6 414
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,109評(píng)論 1 330
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,099評(píng)論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,287評(píng)論 0 291
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,799評(píng)論 1 338
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,515評(píng)論 3 361
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,750評(píng)論 1 375
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,221評(píng)論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,933評(píng)論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,327評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,667評(píng)論 1 296
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,492評(píng)論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,703評(píng)論 2 380

推薦閱讀更多精彩內(nèi)容

  • 整體Retrofit內(nèi)容如下: 1、Retrofit解析1之前哨站——理解RESTful 2、Retrofit解析...
    隔壁老李頭閱讀 6,664評(píng)論 4 31
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,808評(píng)論 25 708
  • 什么是注解(Annotation):Annotation(注解)就是Java提供了一種元程序中的元素關(guān)聯(lián)任何信息和...
    九尾喵的薛定諤閱讀 3,206評(píng)論 0 2
  • 想學(xué)的東西太多了,感覺被時(shí)間拉扯,到頭來啥也沒做成,找到自己喜歡的,才是真的。
    伴_閱讀 57評(píng)論 0 0
  • 當(dāng)我說出話來 你說我無病呻吟 你又怎知我沒病 怎知我這一路多渴望
    原阿原閱讀 253評(píng)論 0 0