一篇文章通俗易懂的讓你徹底理解 Java 註解

很多Java程序員,對Java的註解一知半解,更有甚者,有的人可能連註解是什麼都不知道

本文我們用最簡單的 demo , 最通俗最短的語言,帶你了解註解到底是什麼?

先來簡單回顧一下基礎,我們知道,Java 的源文件編輯後,生成 .class 文件,

  1. .Java源文件,這個是源文件時期
  2. 源文件經過編譯生成 .class 位元組碼文件,這個也是編譯時期
  3. .class 加載到內存中,就可以用了,這個是運行期間

如下圖
image

記住以上知識點,下面和註解有關,我們正式來講註解
本文將從以下 2 個方面來講解註解

  • 1 註解是什麼
  • 2 如何定義一個註解
  • 3 如何使用註解

尤其是第3條,很多人不理解註解,就是因為不知道如何使用註解
3條本文會用最簡單的語言來揭示如何使用

一 註解是什麼?

一句話,註解就和生活中的標籤一樣,比如一個人,這個人可能有 學生標籤,月光族標籤,愛抬杠標籤

二 如何定義一個註解

語法: public @interface 註解名 { }
對的, @interface 是個關鍵字,記住就行了,沒有為什麼
定義註解就是用@interface ,後面跟上註解名

比如定義一個名字叫 info 的註解,如下
新建一個文件 info.java,代碼如下:

package com.demo;

//定義了一個叫做 info 的註解
public @interface info {

}

很簡單吧,上面就定義了一個叫做 info 的註解,下面有2個問題來了

  • 第一個: info 註解用在什麼地方?
    是用到類名上? 還是用在 類的字段上 ? 還是用在類的方法上 ?

  • 第二個:info 註解生命周期(或叫保留策略,我更喜歡叫生命周期)
    註解還有生命周期嗎?答案是當然有了

    前面說過,註解類似標籤,一個人可能剛畢業,有月光族標籤,剛畢業賺的少嘛
    但是有可能過了 3,4 年,技術好了,工資漲上去了,可能就沒有月光族標籤了

    那麼標籤有幾個生命周期呢?就是本文開頭講的,參考上面的圖
    答案是:3 個 ,分別是 源文件期編譯期運行期

就是說:有的註解存在於源文件期,有的標籤存在於編譯期,有的標籤存在於運行期

::: tip
運行期的註解用的最多,本文着重講運行期間,源文件期,編譯期比較簡單
看懂運行期後,可自行學習另外2個

運行期,也就是註解在運行期還存在
:::

我們接下來給 info 註解定義用在類的字段上,並且是存在於運行期間

先上代碼,再解釋,代碼如下:

@Target(ElementType.FIELD)          //註解作用在類的字段上
@Retention(RetentionPolicy.RUNTIME) //註解存在於運行期
public @interface info {
    
}

由上面代碼可以看到,出現了 @Target , @Retention 註解,那麼 @Target , @Retention又是什麼?
答:@Target, @Retention 是元註解,咋又出來一個元註解,可以望文生義:元就是元始的意思,最開始的意思
舉個很簡單的例子來幫助了解元註解是什麼

比如開發一款 IOS APP 軟件,用 xcode 這個軟件開發,那麼 xcode軟件又是用什麼開發的?
定義一個註解,用元註解
是不是很類似,如下圖
image

看過上面的圖應該能理解了,什麼是元註解了吧,就是為了定義註解用的,知道怎麼用就行了
就比如我們開發軟件,要用到各種各樣的開發軟件的IDE,我們不用管這些IDE軟件是哪個軟件開發的
我們只需要知道,元註解就相當於IDE,註解就相當於我們開發的軟件,就OK了

回到上面的info的定義,我們來解釋一下 Target,Retention 這 2 個註解的用處以及能取哪些值

Target 元註解

用處:用來定義註解的用在的地方,比如是用在類上啊,還是用在字段上啊,還是用在方法上啊等
取值:我們列出幾個常用的就行,其它的自行下去查義即可,如下

取值 用在哪
ElementType.TYPE 類或者接口上
ElementType.FIELD 類的字段上
ElementType.METHOD 類的方法上
ElementType.PARAMETER 方法的參數上

Retention 元註解

用處:用來定義註解的生命周期(或叫保留策略,我更喜歡叫生命周期)
取值:就只有3個,如下

取值 存在於哪個時期
RetentionPolicy.SOURCE 源文件期
RetentionPolicy.CLASS 編譯期
RetentionPolicy.RUNTIME 源運行時期

::: tip
元註解都是已經定義好的,我們只管用,只管知道怎麼用就行
就是我們自定義一個註解時才用到元註解,取幾個值,定義一下我們的註解用在哪些地方
存在的時期等,僅此而已
:::


通過上面的敘述,我們小小總結一下

  • 註解就是類似標籤一樣的東西
  • 註解定義是用 public @interface 註解名 { }
  • 註解是有使用的地方和生命周期的
  • 註解能用在類上,字段上,方法上,參數上等
  • 元註解就是用來定義註解的,就像 xcode 軟件是用來開發IOS 軟件一樣的邏輯

下面我們來講第三點,也是最重要的一點,我們學會了自定義註解,怎麼使用呢?

三 如何使用註解

註解一般是和反射一塊用的,不懂反射的,不懂Java的大Class的,一定要看看下面的2篇文章
一篇文章徹底搞懂Java的大Class到底是什麼
一篇文章弄懂 Java 反射的使用

我們來擴展一下上面的 info註解,代碼如下:

@Target(ElementType.FIELD)          //註解作用在類的字段上
@Retention(RetentionPolicy.RUNTIME) //註解存在於運行期
public @interface info {
    String job();       //job屬性
    String comment();   //comment屬性
}

對的,你又看到了註解還能定義屬性,記住,就按照上面的定義就行了。
主要看怎麼用

我們定義一個工人類Worker,如下:

//工人類
public class Worker {
    //工人的名字
    public String name;

    //工人簡介方法,打印工作的基本信息
    public void show(){

    }
}

很簡單的一個類,我們在 name 字段上添加我們定義的info註解,如下

public class Worker {

    //註解是能給屬性傳值的,job和comment和info定義中的相呼應,對,屬性就是這樣用的
    @info(job = "工程師",comment = "工作很努力") 
    public String name;

    public void show(){

    }
}

上面我們給 name 字段添加了我們自己定義的註解,並且給註解中傳了工作的職位是:工程師 ,評價是:工作很努力
我們想在show()方法中,打印出工作的名字,職位,和評價

獲取註解中的 job和 comment可以通過反射獲取 ,注意看注釋,如下

public class Worker {

    //註解是能給屬性傳的,job和comment和定義中的相呼應
    @info(job = "工程師",comment = "工作很努力")
    public String name;

    public void show(){
        //1 獲取本類的位元組碼
        Class clz = this.getClass();

        //2 獲取類中定義的字段
        Field[] fields = clz.getDeclaredFields();

        //3 遍歷字段,看看哪個字段有info註解
        for (Field field : fields){
            //4 判斷此字段上是否有 info 註解
            info annotation = field.getAnnotation(info.class);

            //5 如果不為 null ,說明 field上有info註解
            if (annotation != null){
                //6 通過info註解,獲取info註解中的 job和comment
                String job = annotation.job();
                String comment = annotation.comment();

                //7 打印出來
                System.out.println("我是:" + this.name + " 我的職位是:" + job + "  我的評價是:" + comment);
            }
        }
    }
}

通過上面可以看出,使用註解步驟如下:

  1. 獲取類的 Class ,也就是類的位元組碼
  2. 獲取類的所有字段的字碼碼數組
  3. 遍歷字段
  4. 通過 info annotation = field.getAnnotation(info.class) 獲取字段上對應的註解
  5. 通過註解,獲取註解中傳的值

我們再來寫一個 main 函數,調用上面那段代碼:如下

public class Demo1 {
    public static void main(String[] args){
        Worker worker = new Worker();
        worker.name = "待兔,www.helloworld.net 站長";
        worker.show();
    }
}

打印如下:

我是:待兔,www.helloworld.net 站長 我的職位是:工程師 我的評價是:工作很努力

本文到此,幾乎講完了,註解的很多其它的東西還沒有講,不過不重要,本文最重要的讓你明白什麼是註解,怎麼定義註解,怎麼使用註解
至於註解其它的知識,比如註解怎麼用在方法上,用上類上,等等,都是類似,只需要查一下就行了。
網上很多文章 ,只要能通過本文把註解弄明白了,了解註解其它的就簡單了。