1.基礎語法
註釋定義看起來像接口的定義。事實上,像任何其他接口壹樣,註釋將被編譯成壹個類文件。
@Target(ElementType。方法)
@保留(RetentionPolicy。運行時間)
公共@接口測試{}
除了@符號之外,@Test的定義與空接口非常相似。在定義註釋時,您需要壹些元註釋,比如@Target和@Retention。
@Target用於定義註釋的應用位置(比如方法或字段)。
@Retention用於定義註釋在源代碼、類文件或運行時的哪個級別可用。
在註釋中,通常包含元素來表示某些值。程序可以在分析和處理註釋時使用這些值。沒有元素的標註稱為標記標註。
元標註有四種,元標註負責標註其他標註,所以這四種標註的目標值都是ElementType。批註_類型。
註釋
@ target指示可以使用批註的位置,這由ElementType枚舉定義。
構造函數:構造函數的聲明
字段:域聲明(包括枚舉實例)
局部變量:局部變量聲明
方法:方法聲明
包:包聲明
參數:參數聲明
類型:類、接口(包括註釋類型)或枚舉聲明。
ANNOTATION_TYPE:註釋聲明(應用於另壹個註釋)
TYPE_PARAMETER:類型參數聲明(1.8新增)
TYPE_USE:類型用法聲明(1.8新增)
PS:當註釋沒有指定目標值時,這個註釋可以用在任何元素上,也就是上面的類型。
@ retention指示註釋信息需要保存在哪個級別,這由RetentionPolicy枚舉定義。
SOURCE:註釋會被編譯器丟棄(這種類型的註釋信息只會保留在源代碼中,源代碼編譯後,註釋信息會被丟棄,不會保留在編譯後的類文件中)。
類:註釋在類文件中是可用的,但是會被VM丟棄(這種類型的註釋信息會保留在源代碼和類文件中,執行時不會加載到虛擬機(JVM)中)。
運行時:VM在運行時也會保留註釋信息,所以可以通過反射機制讀取註釋信息(源代碼、類文件和執行時註釋的信息)。
PS:當註釋沒有定義保留值時,缺省值是CLASS。
@ Documented表示註釋將包含在javaapi文檔中。
@ Inherited允許子類從父類繼承註釋。
2.註釋元素
–下列類型可用於註釋元素:
–所有基本類型(int、float、Boolean、byte、double、char、long、short)。
–字符串
–類別
–枚舉
–註釋
–以上類型的數組
如果使用其他類型,編譯器將報告錯誤。也不允許使用任何包裝類型。註釋也可以用作元素的類型,也就是說,註釋可以嵌套。
元素的修飾符只能是public或default。
–默認限額
編譯器對元素的默認值有點挑剔。首先,元素不能有不確定的值。也就是說,在使用註釋時,元素必須要麽具有默認值,要麽提供元素的值。
其次,對於非基本類型的元素,無論是在源代碼中聲明的,還是在註釋接口中定義的,都不能用null作為值。這就是限制,這使得處理器很難表達壹個元素的存在與否,因為所有的元素都存在於每個註釋的聲明中,並有相應的值。為了規避這個限制,只能定義壹些特殊的值,比如空字符串或者負數,表示壹個元素不存在。
@Target(ElementType。方法)
@保留(RetentionPolicy。運行時間)
public @interface MockNull {
public int id()default-1;
公共字符串描述()默認為“”;
}
3.快捷指令
什麽是捷徑?我們先來看看springMVC中的控制器註釋。
@Target({ElementType。類型})
@保留(RetentionPolicy。運行時間)
@已記錄
@組件
公共@接口控制器{
字符串值()默認為“”;
}
可以看到Target應用於類、接口、註釋和枚舉。保留策略是運行時運行時,並且具有字符串類型的value元素。平時用的,基本是這樣的:
@Controller("/your/path ")
公共類MockController { }
這是壹種快捷方式,省略了名稱-值對的語法。下面給出了詳細的解釋:
在註釋中定義了壹個名為value的元素,在應用註釋時,如果該元素是唯壹需要賦值的元素,那麽此時就不需要名稱-值對的語法,圓括號中只給出value元素所需的值。這可以應用於任何合法類型的元素,當然,這將元素名稱限制為值。
4.JDK1.8註釋增強
類型參數和類型用途
在JDK1.8中,ElementType又多了兩個枚舉成員,TYPE_PARAMETER和TYPE_USE,用來定義哪個類型可以被註釋。例如,如果要註釋泛型類型參數:
公共類AnnotationTypeParameter & lt@ TestTypeParam T & gt{}
然後,在定義@TestTypeParam時,必須設置ElementType。@Target處的TYPE_PARAMETER,表示此批註可用於標記類型參數。例如:
@Target(ElementType。類型_參數)
@保留(RetentionPolicy。運行時間)
public @ interface testtype param { }
ElementType。TYPE_USE是用來標註各種類型的,所以上面的例子也可以把TYPE_PARAMETER改成TYPE_USE,壹個標註設置成TYPE_USE,那麽任何類型名都可以被標註。例如,有以下註釋定義:
@Target(ElementType。類型_用途)
@保留(RetentionPolicy。運行時間)
公共@接口測試{}
那麽下列用法說明都是可能的:
列表& lt@ Test Comparable & gtlist 1 = new ArrayList & lt;& gt();
列表& lt?擴展可比& gtlist2 = new ArrayList & lt@ Test Comparable & gt();
@測試字符串文本;
text = (@Test String)新對象();
java.util. @測試掃描儀控制臺;
console = new Java . util . @ Test Scanner(system . in);
PS:以上@測試評論在鉛字右側。註意區分1.8之前的枚舉成員,例如:
@Test java.lang.String文本;
在上面的例子中,很明顯文本變量被標記了,所以使用當前的@Target會導致編譯錯誤,而ElementType。應添加局部變量。
@可重復註釋
註釋@Repeatable是JDK1.8中新加入的,妳大概可以從它的名字含義猜出它的意思(Repeatable)。妳可以在同樣的地方重復同樣的評論。例如:
@Target(ElementType。類型)
@保留(RetentionPolicy。運行時間)
公共@接口過濾器{
string[]value();
}
註釋的用法如下:
@Filter({"/admin ","/main"})
公共類MainFilter { }
更改樣式:
@Filter("/admin ")
@Filter("/main ")
公共類MainFilter {}
在JDK1.8出現之前,這種“風格”是沒有辦法達到的。使用1.8,您可以如下定義@Filter:
@Target(ElementType。類型)
@保留(RetentionPolicy。運行時間)
@Repeatable(Filters.class)
公共@接口過濾器{
字符串值();
}
@Target(ElementType。類型)
@保留(RetentionPolicy。運行時間)
公共@接口過濾器{
篩選器[]值();
}
其實這就是編譯器的優化。使用@Repeatable時,告訴編譯器使用@Filters作為收集重復註釋的容器,每個@Filter都存儲自己指定的字符串值。
JDK1.8向AnnotatedElement接口添加了getDeclaredAnnotationsByType和getAnnotationsByType。當指定@Repeatable的註釋時,它將尋找具有重復註釋的容器。相比之下,getDeclaredAnnotation和getAnnotation不會處理@Repeatable註釋。例子如下:
@Filter("/admin ")
@Filter("/filter ")
公共類FilterClass {
公共靜態void main(String[] args) {
Class & ltFilterClass & gtfilter class class = filter class . class;
filter[]annotationsByType = filter class class . getannotationsbytype(filter . class);
if (annotationsByType!= null) {
for(Filter Filter:annotationsByType){
system . out . println(filter . value());
}
}
system . out . println(filter class class . get annotation(filter . class));
}
}
日誌如下所示:
/admin
/過濾器
空
望采納!