最近看到很多框架都在用注解,包括Android的和javaweb 的,但是對java注解確實不了解,就像之前對反射一樣“只知其名,不知其用”,在昨天看了用法之后在這里做一個總結。
根據我自己的理解,“注解”這個翻譯確實很到位,不像反射一樣給人摸不著頭腦的感覺。“注解”看著其實很像另一個名詞“注釋”,他們倆的作用確實有些像,比如都是用一個東西來解讀另一個東西,只是“注釋”是用自然語言對該段代碼進行解釋讓看的人清楚意思,而注解更多的是對代碼進行解釋讓編譯器清楚意思。我后來又想了一下,好像確實沒有比“注解”更合適的翻譯了。而且“注解”更偏向的是“解”,像解方程一樣對其進行處理。
下面說一下Annotation的用法。 Annotation里面有元注解和自定義注解之分,元注解是對自定義注解進行定義的,我把它比作定義類的一些關鍵字。元注解一共包含以下四個, 四個元注解分別是:@Target,@Retention,@Documented,@Inherited ,其作用分別如下:
@Target: 表示該注解用于什么地方,可能的值在枚舉類 ElemenetType 中,包括: ElemenetType.CONSTRUCTOR———————-構造器聲明 ElemenetType.FIELD ———————————–域聲明(包括 enum 實例) ElemenetType.LOCAL_VARIABLE——————– 局部變量聲明 ElemenetType.METHOD —————————–方法聲明 ElemenetType.PACKAGE —————————– 包聲明 ElemenetType.PARAMETER ————————–參數聲明 ElemenetType.TYPE————————————- 類,接口(包括注解類型)或enum聲明
@Retention: 表示在什么級別保存該注解信息。可選的參數值在枚舉類型 RetentionPolicy 中,包括: RetentionPolicy.SOURCE ———————————注解將被編譯器丟棄 RetentionPolicy.CLASS—————————-注解在class文件中可用,但會被VM丟棄 RetentionPolicy.RUNTIME VM——-將在運行期也保留注釋,因此可以通過反射機制讀取注解的信息。 @Documented: 將此注解包含在 javadoc 中,它代表著此注解會被javadoc工具提取成文檔。在doc文檔中的內容會因為此注解的信息內容不同而不同。相當與@see,@param 等。 @Inherited: 允許子類繼承父類中的注解。
其中“Target”和“Retention”用的比較多。一個是說明該注解的作用的對象,一個是作用在哪些情況下。有些像類的權限符和對象的存活周期。
在使用注解的使用要使用“@”,比如使用元注解的時表示為“@Target”,如@Target(ElemenetType.FIELD)表示的是作用在類的屬性中。同時,在自定義注解時也要用到“@”,并且還要用到的一個關鍵字是“interface”,組合起來就是“@interface”,如
以上就是定義一個注解的方法,是不是猛一看以為是接口呢,其實我在不了解這是注解定義的時候也以為它就是接口呢,了解之后才發現“哦!原來你就是注解啊!偽裝得很深啊!”。
可以看到上面這個注解是有一個參數的,這個參數的類型就是String 參數名是“value”,只是這個后面是一個括號,不明白的還以為是一個抽象方法呢,我后來想之所以用interface,又用這個的定義方法,確實也是又道理的,因為它的使用是有些像接口的感覺,都是只是定義了,然后本身沒有什么用處,只是在里面填寫東西之后才有些用處。
在看講解的時候注意到有一個一般使用習慣,就是在參數只有一個的時候一般將參數名設置為“value”,其實我倒是覺得這些無所謂,但是一般規范的話,大家可以了解一下。
在定義參數的時候可能會需要默認值,定義默認值的方法也非常的簡單,例如為上面的value定義默認值的話就是下面這樣:
String value() default "nn";也就是在value后面加一個default,后面接一個值就行了。
注解的使用基本就是這些了,對了,Java本身還有五個內置的注解,它們雖然是系統定義好的,但和自定義的注解沒有什么區別,所以我把它們也列為自定義注解一類。它們分別是
@Override: 子類中被@Override 修飾的方法,如果存在對應的被重寫的父類方法,則正確;如果不存在,則報錯。 @Override 只能作用于方法,不能作用于其他程序元素。
@DePRecated: 用于表示某個程序元素(類、方法等)已過時。如果使用了被@Deprecated修飾的類或方法等,編譯器會發出警告。 @SuppressWarnings 抑制編譯器警告。指示被@SuppressWarnings修飾的程序元素(以及該程序元素中的所有子元素,例如類以及該類中的方法…..)取消顯示指定的編譯器警告。 例如,常見的@SuppressWarnings(value=”unchecked”)表示當使用集合時沒有用泛型 (Generics) 來指定集合保存的類型; 關閉編譯器警告 @SafeVarargs: @SafeVarargs是JDK 7 專門為抑制“堆污染”警告提供的。
@FunctionalIterface: (Java 8 新增的) 函數式接口。Java8規定:如果接口中只有一個抽象方法(可以包含多個默認方法或多個static方法),該接口稱為函數式接口。 @FunctionalInterface就是用來指定某個接口必須是函數式接口,否則就會編譯出錯。
至于怎么讓注解產生作用呢,那就要用到反射機制了,可以通過反射
Class clazz=Class.forName("com.test.A");Annotation[] arr=clazz.getAnnotations();for (int i = 0; i < arr.length; i++) { System.out.println(arr[i]);}上述clazz.getAnnotations()方法可以獲得包含類A中所有注解的數組
上面這段代碼的作用是先獲得A中名為“name”的Field,之后通過注解A_Field類獲得A_Field的對象 a_f,在獲得a_f對象之后就可以像別的對象一樣對注解中的屬性進行讀取了。
關于注解我的理解和使用目前就是這些,有什么錯誤歡迎批評指正!
新聞熱點
疑難解答