Android-註解
java註解在 Android 中有兩種應用方式,一種方式是基於反射的,在程式的執行期間獲取類資訊進行反射呼叫;另一種是使用註解處理,在編譯期間生成相關程式碼,然後在執行期間通過呼叫這些程式碼來實現相關功能。
我們先了解一下註解的分類及其關鍵字
標準註解(java預設提供) | 元註解(使用者自己定義用) |
---|---|
@Override | @Target |
@Deprecated | @Retention |
@SuppressWarnnings | @Documented |
@SafeVarags | @Inherited |
@Repeatable |
由表格可以看出java中的註解主要分為兩類,標準註解和元註解,。標準註解是 Java 為我們提供的預定義註解,這個我們沒多大關係,主要是元註解,元註解是用來提供給使用者自定義註解用的,接下來我們來學習一下元註解。
JAVA 元註解
先解釋每個註解的含義:
1.元註解之Target
@Target: 註解的作用:
- @Target(ElementType.TYPE) //類、介面、列舉、註解
- @Target(ElementType.FIELD) //類成員(構造方法、方法、成員變數)
- @Target(ElementType.METHOD) //方法
- @Target(ElementType.PARAMETER) //方法引數
- @Target(ElementType.CONSTRUCTOR) //建構函式
- @Target(ElementType.LOCAL_VARIABLE)//區域性變數
- @Target(ElementType.ANNOTATION_TYPE)//註解
- @Target(ElementType.PACKAGE) //包
- @Target(ElementTypeTYPE_PARAMETER) //型別引數宣告
- @Target(ElementType.TYPE_USE) //使用型別
2.元註解之Retention
@Retention:註解的保留位置
- @Retention(RetentionPolicy.SOURCE) //註解僅存在於原始碼中,在class位元組碼檔案中不包含,註解將被編譯器丟棄.
- @Retention(RetentionPolicy.CLASS) // 預設的保留策略,註解會在class位元組碼檔案中存在,但執行時無法獲得,會被JVM丟棄.
- @Retention(RetentionPolicy.RUNTIME) // 註解會在class位元組碼檔案中存在,在執行時可以通過反射獲取到
3.元註解之Document
- @Document:說明該註解將被包含在javadoc中
4.元註解之Inherited
- @Inherited:說明子類可以繼承父類中的該註解
5.元註解之Repeatable
- @Repeatable:在需要對同一種註解多次使用應用於指定物件,往往需要藉助@Repeatable,為java8新增。
瞭解完這些註解的含義,我們來自定義一個,java註解有兩種實現方式。
JAVA自定義註解
1.基於反射使用註解
首先我們的目標是製作一個使用者資訊表,是一個User物件,表中有其對應的屬性,將註解和屬性等關聯,然後再通過反射拿到對應的註解值和屬性值列印,思路如下:
1.1. 首先定義兩個註解UserAnnotation和UserAttribute,建立一個註解遵循: public @interface 註解名 {方法引數}
1.2. 將註解和User物件關聯給使用者賦值。
1.3. 獲取註解,列印註解的註解值和屬性值。
定義註解程式碼如下

image.png
將註解和User物件繫結

image.png
public static void main(String [] args){ UserBean mUserBean =new UserBean(); mUserBean.setUserName("張三"); mUserBean.setUserSex("男"); mUserBean.setUserAge(18); StringBuffer mStringBuffer= printData(mUserBean); System.out.println(mStringBuffer); }
我們主要看一下printData這個列印的程式碼,都有註釋不解釋
private static StringBuffer printData(UserBean userBean){ //建立一個StringBuffer物件拼接資料 StringBuffer mStringBuffer =new StringBuffer(); //根據物件獲取註解Class Class annotationClass =userBean.getClass(); //判斷物件中有沒有我們定義的userAnnotation註解 boolean bUserAnnotation =annotationClass.isAnnotationPresent(CustomeAnnotation.UserAnnotation.class); if(bUserAnnotation){ //獲取userAnnotation註解 CustomeAnnotation.UserAnnotation mUserAnnotation= (CustomeAnnotation.UserAnnotation) annotationClass.getAnnotation(CustomeAnnotation.UserAnnotation.class); //獲取獲取userAnnotation註解的值 String userAnnotationName =mUserAnnotation.userClassName(); mStringBuffer.append(userAnnotationName+"資訊如下:"); //進而獲取物件中的所有屬性 //獲取物件中的所有屬性 Field[] fields = annotationClass.getDeclaredFields(); //便遍歷屬性 for(Field field : fields){ //判斷屬性中是否有我們定義的UserAttribute boolean bUserAttribute =field.isAnnotationPresent(CustomeAnnotation.UserAttribute.class); if(bUserAttribute){ //獲取自定義UserAttribute註解 CustomeAnnotation.UserAttribute userAttribute = field.getAnnotation(CustomeAnnotation.UserAttribute.class); //獲取去userAttribute中的值 String name = userAttribute.userAttribute(); Object value = ""; try { //獲取對應屬性的值,toUpperCase()把字串轉換為大寫 Method method = annotationClass.getMethod("get" + field.getName().substring(0, 1).toUpperCase() + field.getName().substring(1)); value = method.invoke(userBean); } catch (Exception e) { e.printStackTrace(); } //string型別 if (value instanceof String) { mStringBuffer.append(name + "=").append(value).append(","); } else if (value instanceof Integer) { mStringBuffer.append(name + "=").append(value).append(","); } }else{ throw new NullPointerException("UserAttribute not find"); } } }else{//如果不存在拋一個異常 throw new NullPointerException("userAnnotation not find"); } return mStringBuffer; }
這樣的話我們就可以成功打印出資訊了,請問明白了沒,如果沒有明白,沒關係我們繼續在寫一個,類似Butterknife的:
- 第一步定義註解
- 第二步將註解應用於控制元件
-
在App執行時,通過反射將findViewbyId得到的控制元件,注入到註解描述的成員變數中完成繫結。
第一步:
image.png
第二步:
image.png
第三步:

image.png
2. 基於 annotationProcessor 使用註解
這個看到過一篇文章比較專業,我就不再這裡說了
ofollow,noindex">參考