Java入門篇——注解Annotation

在Java1.5以后,引入了注解再层,也稱作元數(shù)據(jù)贸铜。作為新的特性,同時也是基礎(chǔ)知識之一树绩,我們應(yīng)該學(xué)會使用這種用法萨脑,雖然反射會帶來代碼效率問題隐轩,但相比于它的優(yōu)點饺饭,這種損失我們還是可以承受的。

元數(shù)據(jù)被定義為:描述數(shù)據(jù)的數(shù)據(jù)职车,對數(shù)據(jù)及信息資源的描述性信息瘫俊。

我們可以認(rèn)為注解的目的就是對數(shù)據(jù)添加的附加信息。在java源代碼中添加注解悴灵,有助于減輕編寫“樣板”代碼的負(fù)擔(dān)(findViewById)扛芽,更加干凈易讀的代碼以及編譯器類型檢查。

注解的語法比較簡單积瞒,使用一個@符號修飾代表的就是一個注解川尖。Java 5內(nèi)置的幾種注解有

//當(dāng)前的方法定義將覆蓋超類中的方法
@Override
//代表被這個元數(shù)據(jù)修飾的元素已被廢棄,使用已廢棄的方法或?qū)ο缶幾g器會發(fā)出警告
@Deprecated
//關(guān)閉不當(dāng)?shù)木幾g器警告信息茫孔,比如unchecked叮喳,未檢查的類型等
@SuppressWarnings

自定義注解類型

使用@interface來定義注解類型

public @interface Test {
}

使用注解類型

//一般寫法,比較優(yōu)美
@Test
void test(){
    
}

//注解可以看做是一種修飾符缰贝,它的使用和修飾符幾乎一模一樣
// 不太好看馍悟,不建議
public static synchronized @Test void  test(){
    
}

上面簡單定義了一個注解,但是一般我們定義的注解剩晴,還會定義一些注解的類型锣咒,Annotation有四種元注解類型,元注解專職負(fù)責(zé)注解其他的注解赞弥,詳情可以看Java API里面的Annotation

# Retention 
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value();
}

# Target 
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    ElementType[] value();
}

# Documented
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}

# Inherited 
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Inherited {
}

Rentention
Rentention定義該注解在哪一個級別保留該注解信息毅整,可選的RetentionType參數(shù)包含

// 存在于Java源文件,注解被編譯器丟棄
SOURCE
// 存在于Java源文件绽左,以及經(jīng)編譯器后生成的Class字節(jié)碼文件悼嫉,但在運行時VM不再保留注解
CLASS
// 存在于源文件、編譯生成的Class字節(jié)碼文件妇菱,以及保留在運行時VM中承粤,因此可通過反射讀取注解
RUNTIME

**Target **
Target表示該注解可以用于什么地方暴区,可能使用的參數(shù)ElementType包括

// 注解類型,表示這個注解只能用于注解類型
// 比如Target辛臊,Rentention仙粱,Inherited,Documented這些元注解都是用于注解類型的
ANNOTATION_TYPE
// 構(gòu)造器聲明
CONSTRUCTOR
// 字段聲明(包括enum實例)
FIELD
// 局部變量聲明
LOCAL_VARIABLE
// 方法聲明
METHOD
// 包聲明
PACKAGE
// 參數(shù)聲明
PARAMETER
// 類彻舰,接口(包括注解類型)或者enum聲明
TYPE

Documented
當(dāng)前注解的元素會被javadoc工具進(jìn)行文檔化伐割,那么在查看Java API文檔時可查看該注解元素。

Inherited
允許子類繼承父類中的注解

注解元素
在注解中還會包含一些元素表示值刃唤,當(dāng)使用Class里面的方法分析處理注解的時候隔心,程序就可以訪問這些值。在注解中定義元素就像在普通接口中定義方法尚胞,但是注解可以使用default定義元素的默認(rèn)值硬霍。對于沒有元素的注解,我們可以把它作為標(biāo)記來使用笼裳。比如被@Test標(biāo)記的方法為測試方法
注解元素可用的類型包括如下幾個

基本數(shù)據(jù)類型
String
Class
enum
Annotation
以上類型的數(shù)組

對于注解里面的元素唯卖,必須有一個確定的值,不能夠使用null這種未定義的值作為默認(rèn)值躬柬,所以我們可以使用空對象這樣的概念來解決這個問題拜轨,比如定義空字符串作為字符串為null的情況。

解析注解
在很多ORM數(shù)據(jù)庫框架中都使用了注解來定義Bean類允青,直接使用Bean類生成數(shù)據(jù)庫表橄碾。比如ORMLite。

如果不對注解進(jìn)行解析的話颠锉,其實注解就沒什么意義了法牲,可以通過Annotation中提供的API來訪問注解。那么先來看一下Class提供給我們的用于解析注解的結(jié)構(gòu)方法

// 如果當(dāng)前元素包含指定的注解類型木柬,則返回該注解對象皆串,如果不存在則返回null
<A extends Annotation> getAnnotation(Class<A> annotationClass)
// 返回這個元素上的所有注解
Annotation[] getAnnotations()
// 返回直接定義在這個元素上的注解
Annotation[] getDeclaredAnnotations()
// 如果當(dāng)前這個元素包含指定的注解類型則返回true
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

在Android中也有通過注解實現(xiàn)的IOC,我們在編寫程序的時候眉枕,如果xml里面有很多很多的控件恶复,這樣就需要寫很多遍findViewById,不但寫起來很累速挑,而且很占空間谤牡,于是人們就想到了通過注解來減輕這樣的編寫“樣板”代碼的負(fù)擔(dān)。

ViewInject注解類

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface ViewInject {
    int id() default -1;
}

BaseActivity基類姥宝,使用模板方法

public abstract class BaseActivity extends Activity {
    private Context mContext;

    private void inject() {
        Class activity = getClass();
        //獲取Activity內(nèi)所有的字段
        Field[] fields = activity.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            // 獲取指定的注解類型翅萤,如果返回null則跳過
            ViewInject viewInject = field.getAnnotation(ViewInject.class);
            if (viewInject != null) {
                // 獲取指定的屬性
                int value = viewInject.id();
                try {
                    // 反射獲取findViewById方法
                    Method method = activity.getMethod("findViewById", int.class);
                    method.setAccessible(true);
                    // 調(diào)用該方法,因為findViewById要求是在Activity對象上的方法
                    Object object = method.invoke(mContext, value);
                    field.set(mContext, object);
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    protected abstract int requestLayout();

    protected abstract void bindView();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(requestLayout());
        mContext = this;
        inject();
        bindView();
    }
}

MainActivity實現(xiàn)類

public class MainActivity extends BaseActivity {
    @ViewInject(id=R.id.text)
    private TextView textView;

    @Override
    protected int requestLayout() {
        return R.layout.layout_annotation;
    }

    @Override
    protected void bindView() {
        textView.setText("1131");
    }

}

現(xiàn)在大致上那些retrofit腊满,dagger套么,butterknife使用的注解也是基于這個原理的罷培己,有空去好好研究一下這幾個開源框架的源碼,使用注解胚泌,我們應(yīng)該還需要有類加載省咨,泛型,反射等基礎(chǔ)知識玷室,才能夠把注解玩的飛起零蓉。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市穷缤,隨后出現(xiàn)的幾起案子敌蜂,更是在濱河造成了極大的恐慌,老刑警劉巖津肛,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件章喉,死亡現(xiàn)場離奇詭異,居然都是意外死亡快耿,警方通過查閱死者的電腦和手機囊陡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來掀亥,“玉大人,你說我怎么就攤上這事妥色√禄ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵嘹害,是天一觀的道長撮竿。 經(jīng)常有香客問我,道長笔呀,這世上最難降的妖魔是什么幢踏? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮许师,結(jié)果婚禮上房蝉,老公的妹妹穿的比我還像新娘。我一直安慰自己微渠,他們只是感情好搭幻,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著逞盆,像睡著了一般檀蹋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上云芦,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天俯逾,我揣著相機與錄音贸桶,去河邊找鬼。 笑死桌肴,一個胖子當(dāng)著我的面吹牛刨啸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播识脆,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼设联,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了灼捂?” 一聲冷哼從身側(cè)響起离例,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎悉稠,沒想到半個月后宫蛆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡的猛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年耀盗,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片卦尊。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡叛拷,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出岂却,到底是詐尸還是另有隱情忿薇,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布躏哩,位于F島的核電站署浩,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏扫尺。R本人自食惡果不足惜筋栋,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望正驻。 院中可真熱鬧弊攘,春花似錦、人聲如沸拨拓。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渣磷。三九已至婿着,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背竟宋。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工提完, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人丘侠。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓徒欣,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蜗字。 傳聞我的和親對象是個殘疾皇子打肝,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

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

  • 本文章涉及代碼已放到github上annotation-study 1.Annotation為何而來 What:A...
    zlcook閱讀 29,158評論 15 116
  • 什么是注解(Annotation):Annotation(注解)就是Java提供了一種元程序中的元素關(guān)聯(lián)任何信息和...
    九尾喵的薛定諤閱讀 3,163評論 0 2
  • 整體Retrofit內(nèi)容如下: 1、Retrofit解析1之前哨站——理解RESTful 2挪捕、Retrofit解析...
    隔壁老李頭閱讀 6,461評論 4 31
  • 2017年10月23日 周一 晴天 今天霜降粗梭,氣溫驟降很多,已經(jīng)不再處于早晚溫度低的狀態(tài)级零,下雨的時候白天也很冷澀断医,...
    五厘米閱讀 208評論 0 0
  • 最近一切生活照舊,但和冠宇的關(guān)系好像慢慢得到緩解奏纪,很開心鉴嗤!那么就這樣下去吧,戒驕戒躁序调!安靜平淡的維護(hù)好這段友情醉锅,可...
    InGu閱讀 188評論 0 0