自定義注解及注解的使用

注解簡介

注解的英文就是 Annotation猜煮,是在JDK 1.5之后引入的一個(gè)特性,與類败许、接口王带、枚舉是在同一個(gè)層次。它可以聲明在包市殷、類愕撰、字段、方法醋寝、局部變量搞挣、方法參數(shù)等的前面,用來對這些元素進(jìn)行說明音羞,注釋柿究。

注解就是給 java 代碼加上一個(gè)標(biāo)識規(guī)則,javac編譯器在編譯時(shí)就會去檢測應(yīng)用了該注解類的類是否符合標(biāo)識規(guī)則黄选,來約束編碼規(guī)范。

元注解

Java目前只內(nèi)置了三種標(biāo)準(zhǔn)注解,以及四種元注解办陷。

1貌夕、@Target
表示支持注解的程序元素的種類,注解該用于什么地方民镜,ElementType 注解修飾的元素類型啡专,使用ElementType枚舉類來表示:

CONSTRUCTOR:構(gòu)造器的聲明
FIELD:域聲明(包括enum實(shí)例)
LOCAL_VARIABLE:局部變量聲明
METHOD:方法聲明
PACKAGE:  包聲明
PARAMETER:參數(shù)聲明
TYPE:類,接口(包括注解類型)或enum聲明
ANNOTATION_TYPE:注解類型聲明
TYPE_PARAMETER:類型參數(shù)聲明  從jdk1.8開始  制圈、 hide1.8
 TYPE_USE:類型的使用 從jdk1.8開始 们童、 hide1.8

2、@Retention
表示保留時(shí)間的長短慧库,需要在什么級別保存該注解信息馋嗜, RetentionPolicy參數(shù)包括:

SOURCE:注解將被編譯器丟棄。
CLASS:注解在class文件中可用甘磨,但會被VM丟棄济舆。
RUNTIME:VM將在運(yùn)行期也保留注解莺债,因此可通過反射機(jī)制讀取注解的信息。

RetentionPolicy 它是枚舉類椎瘟,分別簡單了解三種類型:

  • RetentionPolicy.SOURCE

    當(dāng)注解保留時(shí)期為 SOURCE 時(shí):表示注解信息只會被保留到源碼和編譯期間肺蔚,當(dāng)javac編譯器編譯源代碼后會將該注解去除儡羔,但是在編譯期間,注解處理器是是可以處理這些注解的仇冯,在編譯完成之后族操,這些注解信息就沒有了比被。

  • RetentionPolicy.CLASS

    當(dāng)注解保留時(shí)期為 CLASS 時(shí):表示注解信息會被保留到編譯時(shí)期,該注解信息會被編譯到.class文件中等缀,但不會被虛擬機(jī)加載到內(nèi)存中尺迂,保留到 Javac 將.java文件編譯成 .class文件冒掌,但是不會隨著 ClassLoader 將該.class文件加載到內(nèi)存中。

  • RetentionPolicy.RUNTIME

    .當(dāng)注解保留時(shí)期為 RUNTIME 時(shí):表示注解信息會被保留到"運(yùn)行時(shí)期"膳音,這是可以通過反射獲取該注解的信息严蓖。Javac會將源文件.java編譯為.class文件氧急,然后通過 ClassLoader 將.class文件加載到內(nèi)存中成為字節(jié)碼,這時(shí)就可以通過反射來獲取對應(yīng)的注解信息毒姨。

3钉寝、@Documented
將此注解包含在Javadoc中。 表示使用該注解的元素應(yīng)被javadoc或類似工具文檔化俘枫,它應(yīng)用于類型聲明鸠蚪,類型聲明的注解會影響客戶端對注解元素的使用师溅。如果一個(gè)類型聲明添加了Documented注解,那么它的注解會成為被注解元素的公共API的一部分蘸鲸。

4窿锉、@Inherited
允許子類繼承父類中的注解。表示一個(gè)注解類型會被自動繼承妙痹,如果用戶在類聲明的時(shí)候查詢注解類型,同時(shí)類聲明中也沒有這個(gè)類型的注解,那么注解類型會自動查詢該類的父類判沟,這個(gè)過程將會不停地重復(fù),直到該類型的注解被找到為止挪哄,或是到達(dá)類結(jié)構(gòu)的頂層(Object)迹炼。

在開發(fā)中最最常用幾個(gè)注解

  • @Override 約束方法必須從父類中覆寫

    復(fù)寫Object 中的equals(Object obj)時(shí)很容將參數(shù)類型定義為當(dāng)前類的類型,如果沒有添加@Override的話那系統(tǒng)會認(rèn)為這個(gè)方法并不是繼承至Object的equals方法砂碉,那么使用兩個(gè)對象進(jìn)行比較就會出現(xiàn)問題刻两。

  • @Deprecated 約束元素已經(jīng)過期,不建議使用滋迈。

  • @SuppressWarning 壓制警告提示户誓。

通過例子驗(yàn)證如何使用注解

通過編寫代碼,更能了解注解帝美,對注解的概念更能清楚证舟。首先,編寫一個(gè)自定義注解類BindView

/**
 * @Author lu an
 * Create Date is  2019/10/9
 * Des  綁定view的注解
 */
//保存的級別到運(yùn)行時(shí)期
@Retention(RetentionPolicy.RUNTIME)
//目標(biāo)->field 字段
@Target(ElementType.FIELD)
public @interface BindView {
    int viewId() default 0;//默認(rèn)0
    boolean onClick() default false;//default表示默認(rèn)
    boolean onLongClick() default false;//default表示默認(rèn)
}

default表示默認(rèn)值 漆枚,也可以不編寫默認(rèn)值的抵知。下面實(shí)現(xiàn)一個(gè)注解工具實(shí)現(xiàn)類:

/**
 * @Author lu an
 * Create Date is  2019/10/9
 * Des  注解工具類
 */
public class InjectUtils {
    public static void init(Activity ctx){
        //獲取Class對象
        Class clazz = ctx.getClass();
        //獲取字段變量
        Field[]fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //判斷是否綁定了BindView
            if(field.isAnnotationPresent(BindView.class)){
                //獲取到BindView對象
                BindView bindView = field.getAnnotation(BindView.class);
                //通過getAnnotation方法取出標(biāo)記了注解的字段viewId
                int viewId = bindView.viewId();
                if(viewId>0){
                    field.setAccessible(true);
                    //獲取到view
                    View childView = ctx.findViewById(viewId);
                    if (childView != null) {
                        //綁定的點(diǎn)擊監(jiān)聽事件
                        if (bindView.onClick() && ctx instanceof View.OnClickListener) {
                            childView.setOnClickListener((View.OnClickListener) ctx);
                        }
                        if (bindView.onLongClick() && ctx instanceof View.OnLongClickListener) {
                            childView.setOnLongClickListener((View.OnLongClickListener) ctx);
                        }
                    }
                }
            }
        }
    }
}

通過反射方式,通過getAnnotation方法取出標(biāo)記了注解的字段viewId立砸,得到了viewId后颗祝,通過上下文findViewById找到對應(yīng)的View控件,bindView.onClick() 對應(yīng)的@BindView(viewId = R.id.btn_annotation,onClick = true)中的onClick值螺戳,ctx instanceof View.OnClickListener則表示Activity是否實(shí)現(xiàn)了點(diǎn)擊接口.

下面就編寫一個(gè)Activity類實(shí)現(xiàn)注解綁定view及其點(diǎn)擊事件:

public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    //綁定view控件 和 綁定view的點(diǎn)擊事件
    @BindView(viewId = R.id.btn_annotation,onClick = true)
    Button mBtnAnnotation;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //注解初始化
        InjectUtils.init(this);
    }
    @Override
    public void onClick(View v) {
        Toast.makeText(this,"Binding View Success",Toast.LENGTH_SHORT).show();
    }
}

@BindView(viewId = R.id.btn_annotation,onClick = true)表示綁定view控件 和 綁定view的點(diǎn)擊事件倔幼,如果只單單綁定view损同,如@BindView(viewId = R.id.btn_annotation)即可鸟款。

當(dāng)你點(diǎn)擊Button時(shí)就會彈出Binding View Success。

總結(jié)

  • 了解注解的基本概念
  • 了解自定義注解與元注解欠雌,注解參數(shù)與默認(rèn)值
  • 如何使用注解富俄,通過反射,在運(yùn)行時(shí)動態(tài)獲取注解信息幕袱。當(dāng)然注解的注解不緊緊只有反射,還有APT(編譯時(shí)注解處理器)和插樁(編譯后處理篩選)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末们豌,一起剝皮案震驚了整個(gè)濱河市望迎,隨后出現(xiàn)的幾起案子辩尊,更是在濱河造成了極大的恐慌康辑,老刑警劉巖轿亮,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件我注,死亡現(xiàn)場離奇詭異迟隅,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)嗽冒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來剿另,“玉大人,你說我怎么就攤上這事雨女。” “怎么了馏臭?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵括儒,是天一觀的道長。 經(jīng)常有香客問我帮寻,道長固逗,這世上最難降的妖魔是什么藕帜? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮贝攒,結(jié)果婚禮上饿这,老公的妹妹穿的比我還像新娘。我一直安慰自己长捧,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布哑子。 她就那樣靜靜地躺著卧蜓,像睡著了一般把敞。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上盛霎,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天愤炸,我揣著相機(jī)與錄音掉奄,去河邊找鬼姓建。 笑死,一個(gè)胖子當(dāng)著我的面吹牛引瀑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播帜矾,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼屡萤,長吁一口氣:“原來是場噩夢啊……” “哼掸宛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起措译,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎规哪,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體塌衰,經(jīng)...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡杯巨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年服爷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了层扶。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烙荷。...
    茶點(diǎn)故事閱讀 39,902評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡终抽,死狀恐怖昼伴,靈堂內(nèi)的尸體忽然破棺而出镣屹,到底是詐尸還是另有隱情,我是刑警寧澤持舆,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布逸寓,位于F島的核電站覆山,受9級特大地震影響竹伸,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜簇宽,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一勋篓、第九天 我趴在偏房一處隱蔽的房頂上張望吧享。 院中可真熱鬧袱箱,春花似錦抢肛、人聲如沸术陶。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宴偿。三九已至钠至,卻和暖如春近哟,著一層夾襖步出監(jiān)牢的瞬間盐股,已是汗流浹背钱豁。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留疯汁,地道東北人谤碳。 一個(gè)月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像搓茬,于是被迫代替她去往敵國和親卷仑。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,843評論 2 354