注解——體系篇

一、前言

本文分析注解體系的主要目的有如下三點(diǎn):

  1. 個(gè)人的知識(shí)體系的梳理,希望能把書由薄讀厚,再由厚讀薄;
  2. 為后續(xù)博文,仿ButterKnife框架的內(nèi)容鋪墊;
  3. ORM類型框架中大量使用到了注解的內(nèi)容,明確注解意義及使用方法,能夠打通學(xué)習(xí)ORM類型框架的任督二脈。

進(jìn)入正題:

  • 用專業(yè)名詞解釋專業(yè)名詞的注解說明版本如下:
  • 個(gè)人認(rèn)為這樣去理解適合于有經(jīng)驗(yàn)的開發(fā)同學(xué)。

    從JDK5開始,Java增加了對(duì)元數(shù)據(jù)(MetaData)的支持,也就是Annotation(即注解),這里介紹的注解,其實(shí)是代碼里的特殊標(biāo)記,這些標(biāo)記可以在編譯、類加載。運(yùn)行時(shí)被讀取,并執(zhí)行相應(yīng)的處理。通過使用注解,程序開發(fā)人員可以在不改變?cè)羞壿嫷那闆r下,在源文件中嵌入一些補(bǔ)充的信息。代碼分析工具、開發(fā)工具和部署工具可以通過改變這些補(bǔ)充信息進(jìn)行驗(yàn)證或者進(jìn)行部署。 ———《瘋狂Java講義》

  • 對(duì)于新手同學(xué),我建議查看frank909的《秒懂,Java 注解(Annotation)你可以這樣學(xué)》戳→文章傳送門

圖1 注解體系結(jié)構(gòu)圖

二、注解體系

1、注解概述

注解提供了一種為程序元素設(shè)置元數(shù)據(jù)的方法,從某些方面來看,注解就像修飾符一樣,可以用于修飾包、類、構(gòu)造器、方法、成員變量、參數(shù)、局部變量的聲明,這些信息被儲(chǔ)存在注解的“name=value”對(duì)中。

注解能被用來為程序元素(類、方法、成員變量)設(shè)置元數(shù)據(jù)。值得指出的是,注解不影響程序代碼的執(zhí)行,無論添加、刪除注解,代碼都始終如一的執(zhí)行。如果希望讓程序中的注解在運(yùn)行時(shí)起一定的作用,只有通過某種配套的工具對(duì)注解中的信息進(jìn)行訪問和處理,訪問和處理注解的工具統(tǒng)稱為APT(Annotation Processing Tool)。

1.1 元數(shù)據(jù)(metadata)

元數(shù)據(jù)(metadata):就是關(guān)于數(shù)據(jù)的數(shù)據(jù)。

  • 示例:
    ①表格中呈現(xiàn)的是數(shù)據(jù),而表格還會(huì)有額外的數(shù)據(jù)來說明表格的作用,這個(gè)就是表格的元數(shù)據(jù)。
    ②數(shù)據(jù)庫中的表存放了數(shù)據(jù),但表還需要有表的定義、字段的定義等,這個(gè)就是數(shù)據(jù)庫表的元數(shù)據(jù)。
    ③XML文件可以存放數(shù)據(jù)。但xml文件的每個(gè)標(biāo)簽還需要有相應(yīng)的描述,這些描述就是XML標(biāo)簽的元數(shù)據(jù)。
  • 元數(shù)據(jù)可以用于創(chuàng)建文檔,跟蹤代碼中的依賴性,甚至執(zhí)行基本編譯時(shí)檢查。

1.2 什么是Annotation

  • JDK5.0通過名為Annotation(注解)的新功能將一個(gè)更通用的元數(shù)據(jù)工具合并到核心 Java 語言中。
  • 注解是可以添加到代碼中的修飾符,對(duì)程序代碼做出一些說明和解釋??梢杂糜诎暶?、類聲明、構(gòu)造方法、方法、字段、參數(shù)和變量。
    這樣就將程序的元素和元數(shù)據(jù)聯(lián)系起來。編譯器就可以將元數(shù)據(jù)存儲(chǔ)在Class文件中。之后虛擬機(jī)和其它對(duì)象可以根據(jù)這些元數(shù)據(jù)來決定如何使用這些程序元素或改變它們的行為。
  • JDK5.0包含了內(nèi)置注解,還支持編寫定制注解。

1.3 注解基本知識(shí)

  • 注解采用“@”標(biāo)記形式 ,后面跟注解類型名稱。通過(name=value)向注解提供參數(shù)數(shù)據(jù)。每次使用這類表示法時(shí),就是在生成注解。
    注解類型和注解的區(qū)別:注解類型類似于類,注解類似于該類的實(shí)例

2、內(nèi)置注解類型

2.1 內(nèi)置注解類型—Override

  • Override 指明被注解的方法必須是重寫超類中的方法。僅能用于方法之上。
    編譯器在編譯源代碼時(shí)會(huì)檢查用@Override標(biāo)注的方法是否有重寫父類的方法。
    舉例如下:
public class InternalAnnotationTest {
    @Override
    public String toString() {
        return super.toString() + " [Override toString]";
    }

    public static void main(String[] args) {
        TestAnnotation test = new TestAnnotation();
        System.out.println(test);
    }
}

2.2 內(nèi)置注解類型—Deprecated

  • Deprecated 指明被注解的方法為過時(shí)的方法,不建議使用了。能用于方法之上。
    當(dāng)編譯調(diào)用到被標(biāo)注為Deprecated的方法的類時(shí),編譯器會(huì)產(chǎn)生警告。
    舉例如下:
public class InternalAnnotationTest {
    …
    @Deprecated
    public void test(){
        System.out.println("[Deprecated Annotation]");
    }
}

2.3 內(nèi)置注解類型—SuppressWarnings

  • SuppressWarnings 指明被注解的方法在編譯時(shí)如果有警告信息,就阻止警告??煞胖萌魏挝恢谩?/li>
  • 它有一個(gè)必需屬性:value,是String[]類型的,指定取消顯示的警告集。警告類型如下:
類型 作用
unused 未被使用的警告
deprecation 使用了不贊成使用的類或方法時(shí)的警告
unchecked 執(zhí)行了未檢查的轉(zhuǎn)換時(shí)的警告
rawtypes 沒有用泛型 (Generics) 的警告
fallthrough 當(dāng) Switch 程序塊直接通往下一種情況而沒有 Break 時(shí)的警告。
path 在類路徑、源文件路徑等中有不存在的路徑時(shí)的警告。
serial 當(dāng)在可序列化的類上缺少 serialVersionUID 定義時(shí)的警告。
finally 任何 finally 子句不能正常完成時(shí)的警告。
all 關(guān)于以上所有情況的警告。

舉例如下:

public class InternalAnnotationTest {
@SuppressWarnings(value={"unchecked", "deprecation"})
    public void test() {
        Map map = new HashMap();
        map.put("name", "Alex");
        System.out.println(map);
    }
}

3、自定義注解類型

格式如下:

[訪問修飾符] @interface 注解類型名 {
     數(shù)據(jù)類型 屬性名() [default 默認(rèn)值];//定義屬性
}

舉例如下:

public @interface AlexDebug{
}

public @interface AlexAnnotation{
    String value();
}

public @interfacle AlexType{
    int age() default 18;
}

4、元注解

元注解:對(duì)注解的注解

  • 為注解類型提供某種元數(shù)據(jù),使用系統(tǒng)預(yù)定義的元注解可以對(duì)我們的注解進(jìn)行注解。
    結(jié)合元注解,我們可以對(duì)自定義注解類型進(jìn)行相當(dāng)大程度的內(nèi)容補(bǔ)充說明

Java的API為我們提供的元注解如下:

4.1 @Target

指定此注解的適用時(shí)機(jī)

  • 在定義注解類型時(shí),使用java.lang.annotation.Target可以定義其適用的時(shí)機(jī)。
    在定義時(shí)要指定為java.lang.annation.ElementType的枚舉值之一:
package java.lang.annotation;

public enum ElementType{
    TYPE,                         //適用于 類,接口,枚舉
    FIELD,                        //適用于 成員字段
    METHOD,                       //適用于 方法
    PARAMETER,                    //適用于 方法的參數(shù)
    CONSTRUCTOR,                 //適用于 構(gòu)造方法
    LOCAL_VARIABLE,              //適用于 局部變量
    ANNOTATION_TYPE,            //適用于 注解類型
    PACKAGE                   //適用于 包
}

舉例如下:

import java.lang.annotation.ElementType;
import java.lang.annotation.Target;

//聲明注解適用于方法
@Target({ElementType.METHOD})
public @interface AlexAnnotation {
}

4.2 @Retention

  • 使用java.lang.annotation.Retention用來告訴編譯器如何處理當(dāng)前注解。
    在使用Retention類型時(shí),需要提供java.lang.annotation.RetentionPolicy的枚舉類型,它的定義如下:
package java.lang.annotation;

public enum RetentionPolicy {
    SOURCE,      //編譯器處理完后,并不將它保留到編譯后的類文件中
    CLASS,         //編譯器將注解保留在編譯后的類文件中,但是在運(yùn)行時(shí)忽略它
    RUNTIME     //編譯器將注解保留在編譯后的類文件中,并在第一次加載類時(shí)讀取它
}

內(nèi)置注解中的Override、SuppressWarnings的RetentionPolicy為SOURCE,而Deprecated為RUNTIME

4.3 @Documented

  • 在默認(rèn)情況下,注解不包括在Javadoc 中,用java.lang.annatation.Documented可以使此注解加入到Javadoc中。
  • 定義為Documented的注解必須要設(shè)置Retention的值為RetentionPolicy.RUNTIME。
    舉例如下:
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface DocAnnotation {
}

4.5 @Inherited

  • 定義的注解類型使用于程序代碼上后,默認(rèn)父類中的注解并不會(huì)繼承至子類中。
    如果想讓父類中的注解被繼承到子類中,可以在定義注解類型時(shí)加上java.lang.annotation.Inherited類型的注解。

舉例如下:

@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Alex{
    String name();
    int value();
}

@Alex(name="John Snow",age=32)
public class Parent{}

class SubClass extends Parent{}

4.6 @Repeatable

  • 意味著注解的值可以同時(shí)取多個(gè)
    @Repeatable是Java1.8加進(jìn)來的新注解,同樣這里我們舉個(gè)例子:
@interface Persons {
    Person[] value();
}

@Repeatable(Persons.class)
@interface HumanBeing{
    String role default "coder";
}


@Person(role="PM")
@Person(role="Teacher")
@Person(role="Reader")
public class Alex{
    
}

三、結(jié)語

1、一個(gè)技術(shù)開發(fā)人員老去的標(biāo)志,絕不是老成穩(wěn)重、沉默寡言,而是不肯再嘗試,不肯再容許自己置身不熟悉的境地。
2、一個(gè)技術(shù)開發(fā)人員開始廢掉的跡象之二,便是沉溺于短期快感之中,不再做長期投入。不再深入研究底層內(nèi)容。在這里,我對(duì)注解相關(guān)的知識(shí)體系進(jìn)行梳理,后續(xù)會(huì)推出更多的內(nèi)容和大家分享。
3、一個(gè)技術(shù)開發(fā)人員開始廢掉的跡象之三,是淪為抵觸的情緒的奴隸。遇到新技術(shù)畏手畏腳,遇困難而退縮。

希望我們一起努力,加油!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 什么是注解(Annotation):Annotation(注解)就是Java提供了一種元程序中的元素關(guān)聯(lián)任何信息和...
    九尾喵的薛定諤閱讀 3,393評(píng)論 0 2
  • 從JDK5開始,Java增加了Annotation(注解),Annotation是代碼里的特殊標(biāo)記,這些標(biāo)記可以在...
    CarlosLynn閱讀 644評(píng)論 0 2
  • 一、概念 ??Annotation(注解)就是Java提供了一種源程序中的元素關(guān)聯(lián)任何信息和任何元數(shù)據(jù)(metad...
    從菜鳥到老菜鳥閱讀 2,247評(píng)論 0 2
  • 整體Retrofit內(nèi)容如下: 1、Retrofit解析1之前哨站——理解RESTful 2、Retrofit解析...
    隔壁老李頭閱讀 8,661評(píng)論 4 31
  • 從JDK5開始,Java增加了Annotation(注解),Annotation是代碼里的特殊標(biāo)記,這些標(biāo)記可以在...
    lay_wn閱讀 988評(píng)論 0 1

友情鏈接更多精彩內(nèi)容