1.註解的意義
註解本身沒有意義,它是作爲一種標記或者註釋存在。需要結合反射、插樁纔有作用
jdk1.5引入,對於被註解的代碼沒有影響
2.元註解
是用於註解的註解:meta-annotation
Target:註解的使用範圍
public enum ElementType {
TYPE, // 類、接口、枚舉類
FIELD, // 成員變量(包括:枚舉常量)
METHOD, // 成員方法
PARAMETER, // 方法參數
CONSTRUCTOR, // 構造方法
LOCAL_VARIABLE, // 局部變量
ANNOTATION_TYPE, // 註解類
PACKAGE, // 可用於修飾:包
TYPE_PARAMETER, // 類型參數,JDK 1.8 新增
TYPE_USE // 使用類型的任何地方,JDK 1.8 新增
}
Retension:註解保留的時間範圍
public enum RetentionPolicy {
SOURCE, // 源文件保留
CLASS, // 編譯期保留,默認值
RUNTIME // 運行期保留,可通過反射去獲取註解信息
}
Documented:用javac生成幫助文檔時,是否保留註解信息
Inherited:被修飾的註解具有繼承性
3.註解的使用場景
(1)source級別:編譯器能獲得註解和註解聲明的類,能夠獲得其所有成員信息,一般用於編譯器生成額外的代碼,如APT技術
(2)class級別:編譯出.class後,通過修改class數據實現修改代碼邏輯的目的,如字節碼增強、插樁等
(3)runtime級別:程序運行期間,通過反射動態獲取註解和類信息,以完成修改,如反射
(4)Android語法檢查,用@DrawableRes檢查參數類型或@IntDef自定義入參類型檢查
4.反射
典型反射代碼應用:反射獲取intent傳值
public static void injectIntent2(Activity activity){
Class<? extends Activity> cls = activity.getClass();
Field[] fields = cls.getDeclaredFields();
for(Field field:fields){
if(field.isAnnotationPresent(InjectIntent.class)){
InjectIntent injectIntent = field.getAnnotation(InjectIntent.class);
String key = injectIntent.value();
Bundle bundle = activity.getIntent().getExtras();
field.setAccessible(true);
try {
field.set(activity,bundle.get(key));
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}