前言
Java 注解(Annotation)又稱 Java 標注,是 JDK5.0 引入的一種注釋機制。重點:和 Javadoc 不同,Java 標注可以通過反射獲取標注內容。
大話空話不用說太多,簡而言之,在編譯器生成類文件時,標注 可以被嵌入到字節碼中。Java 虛擬機可以保留標注內容,在運行時可以獲取到標注內容 。當然它也支持自定義 Java 標注。反射+注解,是不是感覺Java變成一種動態語言?哈哈哈!
我覺得注解可以分為三個部分來講:內置注解,元注解,自定義注解。
一、內置注解
1、@Override 重寫
概念:檢查該方法是否是重寫方法。如果發現其父類,或者是引用的接口中并沒有該方法時,會報編譯錯誤。
- //這個extends 不要在意,我寫上去只是為了更加方便直觀的去理解,Object是萬物之源,不寫也會默認是其子類,不用解釋過多吧?
- public class Annotation1 extends Object{
- @Override
- public String toString (){
- return "我是重新定義過的toString方法";
- }
- }
@Override(重寫),這個大家應該很熟悉,重寫父類的方法。我們可以看下Object類中toString()是什么樣子的。
那么顯而易見,使用了@Override(重寫)注解,方法名、方法參數必須得和父類保持一致,否則會報錯。如下圖所示:
如果不加@Override(重寫)注解,則正常編譯。
2、@Deprecated 過期警告
概念:標記過時方法。如果使用該方法,會報編譯警告。在開發中,我們經常能遇到這樣的情況,如下圖:
在jdk中有大量這樣的方法,我就不舉例了,自己寫一個可能會更加方便理解。
- public class Annotation1 extends Object{
- public static void main(String[] args) {
- testDeprecated.toString1();
- }
- }
- class testDeprecated {
- @Deprecated
- public static String toString1(){
- return "我是重新定義過的toString方法";
- }
- }
注意點:這個不是報錯,只是警告,提醒我們這個方法可能會有問題,可能有更好的方法來實現!
3、@SuppressWarnings 忽略警告
概念:指示編譯器去忽略注解中聲明的警告。
平時開發中,我們會遇到這樣的情況,如下圖:
這也不是錯誤,這是提醒我們,該方法沒有使用到,警告提醒的作用。加上@SuppressWarnings注解后。
- public class Annotation1 extends Object{
- public static void main(String[] args) {
- }
- @SuppressWarnings("all")
- public static void testSuppressWarnings(){
- System.out.println("測試+testSuppressWarnings忽略警告!");
- }
- }
方法成功高亮起來,并且沒有警告提示了!
我們可以點進去看下這個注解為什么需要參數?
看這里,這個不是方法哦,這是參數。
在注解中的參數格式:calss + 參數名 + ()!這個需要強行記憶哦,回頭我們自定義注解時也需要用到。換一種寫法加深理解!如下圖:
注意點:當注解中只有一個參數時,我們無需加上參數名,注解會自動幫我們匹配的。
二、元注解
概念:顧名思義,元注解就是給注解使用的注解!
1、@Retention 作用域-(常用)
概念:表示在什么級別保存該注解信息。在實際開發中,我們一般都寫RUNTIME,除非項目有特殊需求!我們看下@Retention的源碼。
可以看到,需要一個參數,進參數瞅瞅。
- SOURCE:源代碼時有用。
- CLASS:class文件中有用,但會被jvm丟棄。
- RUNTIME:運行時有用。
- 關系:RUNTIME>CLASS>SOURCE
后面我們自定義注解時,每個都需要用該注解!
2、@Documented 作用文檔
概念:將此注解包含在 javadoc 中 ,它代表著此注解會被javadoc工具提取成文檔。
老規矩看下源碼:
無參的注解,作用域為RetentionPolicy.RUNTIME,運行時有用!這個只是用來作為標記,了解即可,在實際運行后會將該注解寫入javadoc中,方便查看。
3、@Target 目標-(常用)
概念:標記這個注解應該是使用在哪種 Java 成員上面!
參數源碼:
注意這里是數組格式的參數,證明可以傳多個值。
- @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)——包
我們來試一下:
目標不對會報錯的哦!我們將其改成方法上!編譯即正常通過。
其他的作用域大家可以去自行嘗試,篇幅問題,無法做到每個都去試一遍!
4、@Inherited 繼承
概念:標記這個注解是繼承于哪個注解類(默認 注解并沒有繼承于任何子類)。
這個很簡單,就是當@InheritedAnno注解加在某個類A上時,假如類B繼承了A,則B也會帶上該注解。
5、新注解-(了解即可)
從 Java 7 開始,額外添加了 3 個注解:
- @SafeVarargs - Java 7 開始支持,忽略任何使用參數為泛型變量的方法或構造函數調用產生的警告。
- @FunctionalInterface - Java 8 開始支持,標識一個匿名函數或函數式接口。
- @Repeatable - Java 8 開始支持,標識某注解可以在同一個聲明上使用多次。
三、自定義注解
我們來定義一個屬于自己的注解。
- @Retention(value = RetentionPolicy.RUNTIME)
- @Target(value = ElementType.METHOD)
- @Inherited
- @interface myAnnotation {
- String name() default "";
- int age() default 18;
- String like();
- String IDCard() default "";
- }
格式:修飾符(pulic)+ @interface +注解名+ {參數等}
可利用default 設置默認值,設定了默認值后使用注解時不傳值也不會報錯,反之報錯!
我們只需要傳沒有默認值的參數即可。
如果不傳則報錯:
總結
主要就是要注意元注解的使用,因為我們自定義注解時必須得用到!其實注解主要配合反射來用,在此就不展開來敘述了。
原文地址:https://mp.weixin.qq.com/s/F-I7FofDcbFIDeemtk0bsA