Annotation 註解相信大家平時經常用到,比如常見的有@Override @Deprecated @SuppressWarnings
還有很多第三方框架也用到了自定義註解,以前一直覺得很神奇,其實學習自定義才發現還是很簡單的嘛
什麼是註解?
由於不擅言辭,我就直接引用大神的博客介紹了,以下是大神博客地址
http://blog.csdn.net/hai_qing_xu_kong/article/details/51779695 點擊打開鏈接
註解是一種元數據, 可以添加到java代碼中. 類、方法、變量、參數、包都可以被註解,註解對註解的代碼沒有直接影響
首先了解下元註解,
元註解就是用來定義註解的註解.其作用就是定義註解的作用範圍, 使用在什麼元素上等等,
元註解共有四種@Retention, @Target, @Inherited, @Documented
@Target:
@Target說明了Annotation所修飾的對象範圍:Annotation可被用於 packages、types(類、接口、枚舉、Annotation類型)、類型成員(方法、構造方法、成員變量、枚舉值)、方法參數和本地變量(如循環變量、catch參數)。在Annotation類型的聲明中使用了target可更加明晰其修飾的目標。
作用:用於描述註解的使用範圍(即:被描述的註解可以用在什麼地方)
取值(ElementType)有:
1.CONSTRUCTOR:用於描述構造器
2.FIELD:用於描述域
3.LOCAL_VARIABLE:用於描述局部變量
4.METHOD:用於描述方法
5.PACKAGE:用於描述包
6.PARAMETER:用於描述參數
7.TYPE:用於描述類、接口(包括註解類型) 或enum聲明
@Retention:
@Retention定義了該Annotation被保留的時間長短:某些Annotation僅出現在源代碼中,而被編譯器丟棄;而另一些卻被編譯在class文件中;編譯在class文件中的Annotation可能會被虛擬機忽略,而另一些在class被裝載時將被讀取(請注意並不影響class的執行,因爲Annotation與class在使用上是被分離的)。使用這個meta-Annotation可以對 Annotation的“生命週期”限制。
作用:表示需要在什麼級別保存該註釋信息,用於描述註解的生命週期(即:被描述的註解在什麼範圍內有效)
取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在運行時有效(即運行時保留)
@Documented:
@Documented用於描述其它類型的annotation應該被作爲被標註的程序成員的公共API,因此可以被例如javadoc此類的工具文檔化。Documented是一個標記註解,沒有成員。
@Inherited:
@Inherited 元註解是一個標記註解,@Inherited闡述了某個被標註的類型是被繼承的。如果一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類。
注意:@Inherited annotation類型是被標註過的class的子類所繼承。類並不從它所實現的接口繼承annotation,方法並不從它所重載的方法繼承annotation。
當@Inherited annotation類型標註的annotation的Retention是RetentionPolicy.RUNTIME,則反射API增強了這種繼承性。如果我們使用java.lang.reflect去查詢一個@Inherited annotation類型的annotation時,反射代碼檢查將展開工作:檢查class和其父類,直到發現指定的annotation類型被發現,或者到達類繼承結構的頂層。
其中, @Retention是定義保留策略, 直接決定了我們用何種方式解析. SOUCE級別的註解是用來標記的, 比如Override, SuppressWarnings. 我們真正使用的類型是CLASS(編譯時)和RUNTIME(運行時)
自定義註解:
使用@interface自定義註解時,自動繼承了java.lang.annotation.Annotation接口,由編譯程序自動完成其他細節。在定義註解時,不能繼承其他的註解或接口。@interface用來聲明一個註解,其中的每一個方法實際上是聲明瞭一個配置參數。方法的名稱就是參數的名稱,返回值類型就是參數的類型(返回值類型只能是基本類型、Class、String、enum)。可以通過default來聲明參數的默認值。
以上很大一篇都是詳細介紹註解的,現在直接來自定義吧
我總共創建了4個類,Person 和 PersonAttr 就是定義的註解,LaoFuzi是使用註解的類,MainActivity是運行效果的類
先看下Person
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定義用於方法描述的註解
* Created by Alex on 2017/11/23.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Person {
boolean beautiful() default false;
int age() default 0;
String name() default "Alex";
}
這個註解用於方法的描述,所以用@Target({ElementType.METHOD}),保存時機一般都是用@Target({ElementType.METHOD}),因爲我們絕大部分都是需要運行時用
內部定義了幾個方法,後面的返回的默認值,返回值必須是可以定義常量的類型
再看下PersonAttr
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定義用於成員變量描述的註解
* Created by Alex on 2017/11/23.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
public @interface PersonAttr {
String value();
}
這個註解用於描述成員變量,比如很多請求框架都用到,便於解析字段,跟Person差不多,只是@Target({ElementType.FIELD})這裏改變了下,當然還可以定義其他類型
LaoFuzi,使用剛纔定義的註解,方法和成員變量都用到了
public class LaoFuzi {
@PersonAttr("name")
public String name;
@Person(beautiful = false, age = 28, name = "老夫子")
public void printPersonInfo() {
}
}
最後看下效果
private static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Method[] methods = LaoFuzi.class.getDeclaredMethods();
for (Method method: methods) {
Person person = method.getAnnotation(Person.class);
if (person != null) {
Log.d(TAG, person.name() + " " + person.age() + " " + person.beautiful());
}
}
Field[] fields = LaoFuzi.class.getDeclaredFields();
for (Field field : fields) {
PersonAttr personAttr = field.getAnnotation(PersonAttr.class);
if (personAttr != null) {
Log.d(TAG, personAttr.value());
}
}
}
打印結果:
11-23 15:41:31.617 9793-9793/android.example.com.customannotationdemo D/MainActivity: 老夫子 28 false
11-23 15:41:31.617 9793-9793/android.example.com.customannotationdemo D/MainActivity: name
demo 地址
http://download.csdn.net/download/msn465780/10130482 點擊打開鏈接
到這裏已經完成了自定義註解,是不是很簡單啊,又可以愉快的玩耍了