<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          java中注解的使用

          共 4827字,需瀏覽 10分鐘

           ·

          2020-11-17 02:09

          點(diǎn)擊上方「藍(lán)字」關(guān)注我們

          0x01. 說前面

          使用注解開發(fā)的好處

          1.?使代碼更加干凈易讀,易于維護(hù)修改。比如,以前使用spring的開發(fā),都是基于xml文件實(shí)現(xiàn)了統(tǒng)一的配置管理,但是缺點(diǎn)也是顯而易見的,就是隨著項(xiàng)目的越來越大,xml文件會(huì)變得越來越復(fù)雜,維護(hù)成本也會(huì)越來越高。使用注解就可以提供更大的便捷性,易于維護(hù)修改。

          2. 可以實(shí)現(xiàn)代碼的類型檢查,特別是在編譯器的角度實(shí)現(xiàn)一些類型檢查,比如預(yù)檢查(@Override)和抑制警告(@SuppressWarnings)等。

          3. 自定義注解,作為額外信息的載體,存儲(chǔ)有關(guān)程序的額外信息


          0x02.?注解的分類以及使用

          Java注解是附加在代碼中的一些元信息,用于編譯和運(yùn)行時(shí)進(jìn)行解析和使用,起到說明、配置的功能。

          注解不會(huì)影響代碼的實(shí)際邏輯,僅僅起到輔助性的作用。包含在java.lang.annotation包中。注解的定義類似于接口的定義,使用@interface來定義,定義一個(gè)方法即為注解類型定義了一個(gè)元素,方法的聲明不允許有參數(shù)或throw語句,返回值類型被限定為原始數(shù)據(jù)類型、字符串String、Class、enums、注解類型,或前面這些的數(shù)組,方法可以有默認(rèn)值。注解并不直接影響代碼的語義,但是他可以被看做是程序的工具或者類庫。它會(huì)反過來對(duì)正在運(yùn)行的程序語義有所影響。注解可以從源文件、class文件或者在運(yùn)行時(shí)通過反射機(jī)制多種方式被讀取。

          一般來說,注解一般分為三種類型:元注解,標(biāo)準(zhǔn)注解,自定義注解

          2.1 元注解

          元注解是專職負(fù)責(zé)注解其他注解,主要是標(biāo)明該注解的使用范圍,生效范圍。我們是不能改變它的,只能用它來定義我們自定義的注解。

          包括 @Retention @Target @Document @Inherited四種。(java.lang.annotation中提供,為注釋類型)。

          注解說明
          @Target定義注解的作用目標(biāo),也就是可以定義注解具體作用在類上,方法上,還是變量上
          @Retention定義注解的保留策略。RetentionPolicy.SOURCE:注解僅存在于源碼中,在class字節(jié)碼文件中不包含;RetentionPolicy.CLASS:默認(rèn)的保留策略,注解會(huì)在class字節(jié)碼文件中存在,但運(yùn)行時(shí)無法獲得;RetentionPolicy.RUNTIME:注解會(huì)在class字節(jié)碼文件中存在,在運(yùn)行時(shí)可以通過反射獲取到。
          @Document說明該注解將被包含在javadoc中
          @Inherited說明子類可以繼承父類中的該注解

          Target類型主要依賴于ElementType這個(gè)類型,具體的類型如下:

          Target類型說明
          ElementType.TYPE接口、類、枚舉、注解
          ElementType.FIELD字段、枚舉的常量
          ElementType.METHOD方法
          ElementType.PARAMETER方法參數(shù)
          ElementType.CONSTRUCTOR構(gòu)造函數(shù)
          ElementType.LOCAL_VARIABLE局部變量
          ElementType.ANNOTATION_TYPE注解
          ElementType.PACKAGE

          2.2 標(biāo)準(zhǔn)注解

          Java標(biāo)準(zhǔn)注解提供了三個(gè),定義在java.lang中的注解,我認(rèn)為這三個(gè)注解的作用更多的是一種注釋

          • @Override 表示當(dāng)前方法覆蓋父類中的方法。

          • @Deprecated 標(biāo)記一個(gè)元素為已過期,避免使用

          支持的元素類型為:CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE

          • @SuppressWarnings 不輸出對(duì)應(yīng)的編譯警告

          一個(gè)簡(jiǎn)單的使用demo:

          @SuppressWarnings(value?=?{"unused",?"rawtypes"})
          public?class?Children??extends?Parent{
          ????@Override
          ????public?void?work()?{
          ????????System.out.println("我是一個(gè)被重寫的方法");
          ????}

          ????@Deprecated
          ????public?void?play(){
          ????????System.out.println("這個(gè)方法不推薦使用了");
          ????}
          }

          2.3 自定義注解實(shí)現(xiàn)一個(gè)sql語句的拼接

          需要注意的方面:注解的定義類似于接口的定義,使用@interface來定義,定義一個(gè)方法即為注解類型定義了一個(gè)元素,方法的聲明不允許有參數(shù)或throw語句,返回值類型被限定為原始數(shù)據(jù)類型、字符串String、Class、enums、注解類型,或前面這些的數(shù)組,方法可以有默認(rèn)值。

          自定義注解一般可以分為三步:定義注解,使用注解,讀取注解

          定義注解

          @Target(ElementType.TYPE)?//注解加載類上
          @Retention(RetentionPolicy.RUNTIME)?//?運(yùn)行時(shí)讀取注解

          public?@interface?Table?{
          ????String?value();?
          }


          @Target(ElementType.FIELD)
          @Retention(RetentionPolicy.RUNTIME)
          public@interface?UserFiled?{
          ????String?name();
          ????String?type();
          ????int?length();
          }

          使用注解

          //?將自定義的注解加在用戶上,實(shí)現(xiàn)一個(gè)表的映射
          @Table(value?=?"user_table")
          public?class?User?{

          ????@UserFiled(name?=?"user_id",type?=?"int",length?=?8)
          ????private?int?userId;

          ????@UserFiled(name?=?"user_name",type?=?"varchar",length?=?16)
          ????private?String?userName;

          ????@UserFiled(name?=?"password",type?=?"varchar",length?=?16)
          ????private?String?password;

          ????public?int?getUserId()?{
          ????????return?userId;
          ????}

          ????public?void?setUserId(int?userId)?{
          ????????this.userId?=?userId;
          ????}

          ????public?String?getUserName()?{
          ????????return?userName;
          ????}

          ????public?void?setUserName(String?userName)?{
          ????????this.userName?=?userName;
          ????}

          ????public?String?getPassword()?{
          ????????return?password;
          ????}

          ????public?void?setPassword(String?password)?{
          ????????this.password?=?password;
          ????}
          }

          讀取注解的內(nèi)容

          /**
          ?*?讀取注解中的值
          ?*/

          public?class?GetUser?{
          ????public?static?void?main(String[]?args)?throws?ClassNotFoundException,?NoSuchFieldException?{
          ????????Class?userClass?=?Class.forName("annocation.blog.User");

          ????????//?讀取類上的注解
          ????????Table?table?=?(Table)?userClass.getAnnotation(Table.class);
          ????????System.out.println(table.value());

          ????????//?讀取屬性上注解
          ????????Field?userId?=?userClass.getDeclaredField("userId");
          ????????UserFiled?userFiledId?=?userId.getAnnotation(UserFiled.class);
          ????????System.out.println(userFiledId.length()?+?"----"?+?userFiledId.type()?+?"-----"?+?userFiledId.name());

          ????????Field?userName?=?userClass.getDeclaredField("userName");
          ????????UserFiled?userFiledName?=?userName.getAnnotation(UserFiled.class);
          ????????System.out.println(userFiledName.length()+"----"+userFiledName.type()+"----"+userFiledName.name());

          ????????Field?password?=?userClass.getDeclaredField("password");
          ????????UserFiled?userFiledPassword?=?password.getAnnotation(UserFiled.class);
          ????????System.out.println(userFiledPassword.name()?+?"-----"?+?userFiledPassword.type()?+?"-----"?+?userFiledPassword.length());

          ????????//?拼接一個(gè)sql語句
          ????????String?name?=?"chenwei";
          ????????String?sql?="select?*?from"?+?table.value()+"where"+userFiledName.name()+"="+name;
          ????}
          }

          結(jié)果:

          user_table
          user_id----int-----8
          user_name----varchar----16
          password-----varchar-----16

          自定義注解的實(shí)現(xiàn)過程:

          1.?定義注解

          2.?使用注解,根據(jù)自己定義的注解來達(dá)到一些目的,本例中,就是使用注解來完成數(shù)據(jù)庫表和實(shí)體類的映射關(guān)系

          3.?讀取注解的內(nèi)容,也是比較重要的一部分,核心還是利用了反射的思想,得到使用注解的這個(gè)類,根據(jù)類中的getAnnotion的方法得到定義的注解,獲得注解上的值。


          0x03. 注解的實(shí)現(xiàn)的原理

          注解的實(shí)現(xiàn)的原理很大的一部分是基于反射實(shí)現(xiàn)。

          反射可以獲取到Class對(duì)象,進(jìn)而獲取到Constructor、Field、Method等實(shí)例,點(diǎn)開源碼結(jié)構(gòu)發(fā)現(xiàn)Class、Constructor、Field、Method等均實(shí)現(xiàn)了AnnotatedElement接口,AnnotatedElement接口的方法如下

          //?判斷該元素是否包含指定注解,包含則返回true
          boolean?isAnnotationPresent(Class?annotationClass)

          //?返回該元素上對(duì)應(yīng)的注解,如果沒有返回null
          ?T?getAnnotation(Class?annotationClass);

          //?返回該元素上的所有注解,如果沒有任何注解則返回一個(gè)空數(shù)組
          Annotation[]?getAnnotations();

          //?返回指定類型的注解,如果沒有返回空數(shù)組
          T[]?getAnnotationsByType(Class?annotationClass)

          //?返回指定類型的注解,如果沒有返回空數(shù)組,只包含直接標(biāo)注的注解,不包含inherited的注解
          T?getDeclaredAnnotation(Class?annotationClass)

          //?返回指定類型的注解,如果沒有返回空數(shù)組,只包含直接標(biāo)注的注解,不包含inherited的注解
          T[]?getDeclaredAnnotationsByType

          //?返回該元素上的所有注解,如果沒有任何注解則返回一個(gè)空數(shù)組,只包含直接標(biāo)注的注解,不包含inherited的注解
          Annotation[]?getDeclaredAnnotations();

          通過一個(gè)實(shí)例再次說明一下注解的使用過程:

          定義注解

          @Documented
          @Target({ElementType.TYPE,?ElementType.FIELD,ElementType.METHOD})
          @Retention(RetentionPolicy.RUNTIME)
          public?@interface?MyAnnotaion?{
          ????String?getValue()?default?"this?is?myAnntaion";
          ????int?order()?default?0;
          }

          使用注解

          @MyAnnotaion(getValue?=?"annotation?on?class")
          public?class?Demo?{

          ????@MyAnnotaion(getValue?=?"annotation?on?filed")
          ????public?String?name;

          ????@MyAnnotaion(getValue?=?"annotation?on?method")
          ????public?void?hello(){
          ????}

          ????@MyAnnotaion
          ????public?void?defaultMethod(){

          ????}
          }

          利用反射讀取注解中的值。

          public?class?TestDemo?{
          ????public?static?void?main(String[]?args)?throws?NoSuchFieldException,?NoSuchMethodException?{
          ????????/**
          ?????????*?獲取類上的注解
          ?????????*/

          ????????Class?demoClass?=?Demo.class;
          ????????Annotation[]?annotaion?=?demoClass.getAnnotations();
          ????????printAnnotation(annotaion);

          ????????/**
          ?????????*?讀取成員變量上的注解
          ?????????*/

          ????????Field?name?=?demoClass.getField("name");
          ????????Annotation[]?getOnFiled?=?name.getAnnotations();
          ????????printAnnotation(getOnFiled);

          ????????/**
          ?????????*?讀取方法上的注解
          ?????????*/

          ????????Method?hello?=?demoClass.getMethod("hello",?null);
          ????????MyAnnotaion?onMethod?=?hello.getAnnotation(MyAnnotaion.class);
          ????????System.out.println(onMethod.getValue());

          ????????/**
          ?????????*?獲取默認(rèn)方法上的注解
          ?????????*/

          ????????Method?defaultMethod?=?demoClass.getMethod("defaultMethod",?null);
          ????????MyAnnotaion?onDefaultMethod?=?defaultMethod.getAnnotation(MyAnnotaion.class);
          ????????System.out.println(onDefaultMethod.getValue());

          ????}

          ????public?static?void?printAnnotation(Annotation...?annotations)?{
          ????????for?(Annotation?annotation?:?annotations)?{
          ????????????System.out.println(annotation);
          ????????}
          ????}
          }

          運(yùn)行結(jié)果

          @annocation.MyAnnotaion(getValue=annotation?on?class,?order=0)
          @annocation.MyAnnotaion(getValue=annotation?on?filed,?order=0)
          annotation?on?method
          this?is?myAnntaion

          掃碼二維碼

          獲取更多精彩

          Java樂園

          有用!分享+在看?
          瀏覽 50
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  伊人亚洲 | 婷婷丁香激情五月 | 深爱五月丁香 | 91人妻无码成人精品一区二区三区 | 水多多精品视频 |