Java基礎:注解

系列閱讀

1. 概述

注解相當于一種標記蝉衣,在程序中加了注解就等于為程序打上了某種標記,沒加万搔,則等于沒有某種標記锋喜,以后尾序,javac編譯器,開發(fā)工具和其他程序可以用反射來了解你的類及各種元素上有無何種標記仆嗦,看你有什么標記,就去干相應的事先壕。標記可以加在包瘩扼,類,字段垃僚,方法集绰,方法的參數以及局部變量上

開發(fā)中常見注解:

  • @Override:作用在方法上的注解。當方法不是重寫父類的方法時會報錯
  • @Deprecated:作用在方法上谆棺。標記該方法為作廢方法(已過時)
  • @SuppressWarnings:作用在方法上栽燕,壓制警告

2. 注解類型

8種基本數據類型,String,Class碍岔,enum浴讯,annotation,以上類型的數組類型

3. 定義注解

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ViewInject {
    int value();//當使用注解時蔼啦,如果只給名為value的屬性賦值時榆纽,可以省略“value=”
    String name() default "zhangsan";//默認值
}

@interface

使用@interface聲明一個注解類

@Target

表示注解的作用目標,是一個枚舉值

作用目標 說明
ElementType.FIELD 作用于成員變量
ElementType.METHOD 作用于方法
ElementType.CONSTRUCTOR 作用于構造方法
ElementType.PARAMETER 作用于方法的參數

@Retention

表示注解的保存策略捏肢,也是一個枚舉值

注解的保留策略是指奈籽,注解是只保留在源代碼上,還是保留到class文件上猛计,再或者是類在運行時唠摹,可以被類加載器加載到內存中。

如果希望注解被反射奉瘤,那么注解就要保留到運行時勾拉,而不是源代碼或類文件上。

指定注解的保留策略需要使用元注解@Retention盗温,它有一個value屬性藕赞,類型為RetentionPolicy類型,RetentionPolicy是枚舉類型

保存策略 說明
RetentionPolicy.SOURCE 注解只保存在源代碼中卖局,即.java文件
RetentionPolicy.CLASS 注解保存在字節(jié)碼中,即.class文件
RetentionPolicy.RUNTIME 注解保存在內存中的字節(jié)碼斧蜕,可用于反射

注解的屬性

String name() default "zhangsan";//默認值

定義注解的屬性,有點像java類中的方法砚偶,上面的代碼定義了一個類型為String類型批销,注解名為name的屬性,default是給注解設置默認值

value屬性

String value() default "xxx"; 

如果注解中有一個名稱為value的屬性染坯,且你只想設置value屬性(即其他屬性都采用默認值或者你只有一個value屬性)均芽,那么可以省略value=部分,例如:@MyAnnotation("AllenIverson")

數組類型的屬性

int [] arrayAttr() default {1,2,3};//定義
@MyAnnotation(arrayAttr={2,3,4})//使用

如果數組屬性中只有一個元素单鹿,這時候屬性值部分可以省略大括

4. Annotation

4.1 注解的應用結構圖

Annotation

4.2 反射注解

類上的注解:使用Class獲取

  • Class.getAnnotation():獲取指定類型的注解
  • Class.getAnnotations():獲取所有的注解
  • Class.getDeclaredAnnotations():獲取除了繼承得到的所有注解

方法上的注解:使用Method獲取

  • Method.getAnnotation() :獲取方法上指定類型的注解
  • Method.getAnnotations():獲取所有的注解
  • Method.getDeclaredAnnotations():獲取除了繼承得到的所有注解

構造方法上的注解:使用Constructor獲取

  • Constructor.getAnnotation()獲取指定類型的注解
  • Constructor.getAnnotations()獲取所有的注解
  • Constructor.getDeclaredAnnotations() 獲取除了繼承得到的所有注解

屬性上的注解:使用Field獲取

  • Field.getAnnotation():獲取字段上指定類型的注解
  • Field.getAnnotations():獲取所有的注解
  • Field.getDeclaredAnnotations():獲取字段所有的注解

定義注解

@Retention(RetentionPolicy.RUNTIME) 
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyAnn {
    String value() default "hello";
    int value1() default 100;
}

使用注解

@MyAnn(value="hello world", value1=200)
public class MyClass {
    private int a;
    
    @MyAnn("myMethod") 
    public void fun() {}
}

通過反射讀取注解

public class Demo1 {
    public static void main(String[] args) throws Exception {
        Class clazz = MyClass.class;
        MyAnn myAnn = (MyAnn) clazz.getAnnotation(MyAnn.class); 
        System.out.println(myAnn.value()); 
        System.out.println(myAnn.value1()); 
        
        Method method = clazz.getMethod("fun");
        MyAnn myAnn1 = method.getAnnotation(MyAnn.class); 
        System.out.println(myAnn1.value());
        System.out.println(myAnn1.value1());
    }
}

4.3 實現注解小框架

public class ViewUtils {
    public static void inject(Activity activity) throws IllegalAccessException {
        bindView(activity);
    }

    private static void bindView(Activity activity) throws IllegalAccessException {
        Field[] fields = activity.getClass().getDeclaredFields();
        for (Field field : fields){
            ViewInject viewInject = field.getAnnotation(ViewInject.class);
            if (viewInject != null){
                int resId = viewInject.value();
                View view = activity.findViewById(resId);
                field.setAccessible(true);
                field.set(activity,view);
            }
        }
    }

    public static void onClick(final Activity activity){
        Method[] methods = activity.getClass().getDeclaredMethods();
        for (final Method method : methods){
            Onclick onclick = method.getAnnotation(Onclick.class);
            if (onclick != null){
                int resId = onclick.value();
                final View view = activity.findViewById(resId);
                view.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        method.setAccessible(true);
                        try {
                            method.invoke(activity,view);
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        } catch (InvocationTargetException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
        }
    }
}

5. Annotation Processing Tool

編譯時注解在項目編譯的時候生成新的Java文件掀宋,這樣可以減少手動的代碼輸入,而且可以不用使用反射仲锄,對程序不會造成性能影響劲妙。

Android公共技術點之二-Annotation Processing Tool

Annotation-Processing-Tool詳解

6. javapoet

動態(tài)生成Java源碼,ButterKnife使用了該框架儒喊,實現了編譯時注解

javapoet——讓你從重復無聊的代碼中解放出來

7. 注解框架

  • Dagger1
  • Dagger2
  • Guice
  • Butterknife
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末镣奋,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子怀愧,更是在濱河造成了極大的恐慌唆途,老刑警劉巖富雅,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現場離奇詭異肛搬,居然都是意外死亡没佑,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進店門温赔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蛤奢,“玉大人,你說我怎么就攤上這事陶贼∑》罚” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵拜秧,是天一觀的道長痹屹。 經常有香客問我,道長枉氮,這世上最難降的妖魔是什么志衍? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮聊替,結果婚禮上楼肪,老公的妹妹穿的比我還像新娘。我一直安慰自己惹悄,他們只是感情好春叫,可當我...
    茶點故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著泣港,像睡著了一般暂殖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上当纱,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天呛每,我揣著相機與錄音,去河邊找鬼惫东。 笑死莉给,一個胖子當著我的面吹牛毙石,可吹牛的內容都是我干的廉沮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼徐矩,長吁一口氣:“原來是場噩夢啊……” “哼滞时!你這毒婦竟也來了?” 一聲冷哼從身側響起滤灯,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤坪稽,失蹤者是張志新(化名)和其女友劉穎曼玩,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體窒百,經...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡黍判,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了顷帖。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡渤滞,死狀恐怖贬墩,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情妄呕,我是刑警寧澤陶舞,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站绪励,受9級特大地震影響肿孵,放射性物質發(fā)生泄漏。R本人自食惡果不足惜优炬,卻給世界環(huán)境...
    茶點故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一颁井、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蠢护,春花似錦雅宾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至懈凹,卻和暖如春蜀变,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背介评。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工库北, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人们陆。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓寒瓦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親坪仇。 傳聞我的和親對象是個殘疾皇子杂腰,可洞房花燭夜當晚...
    茶點故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內容