Java基礎筆記(註解)
1 註解
註解是放在Java原始碼的類、方法、欄位、引數前的一種標籤。 註解本身對程式碼的邏輯沒有任何影響,如何使用註解是有工具決定的,比如編輯器可以使用註解,它可以使用JDKd定義的註解,註解本身對程式碼沒有影響,但寫了註解,編譯器可以幫助我們解決問題,不寫就不檢查,JDK定義的常用註解有:
@Override
:讓編譯器檢查該方法是否正確地實現覆寫@Deprecated
:告訴編譯器該方法已經作廢,在別處使用會出現警告@SuppressWarning
:取消警告
1.1 定義註解
使用註解的時候可以傳入配置引數,配置引數在建立註解型別時定義,配置引數可以包括:
- 所有基本型別
String
- 列舉型別
- 基本型別的陣列
傳入配置引數必須是常量而不能是變數,如果缺少某個配置引數將使用預設值,如果只寫常量,相當於將該常量賦值給 value
引數,如果只寫註解,相當於全部使用預設值。
定義註解的時候,使用 @interface
定義註解
- 註解的引數宣告類似宣告一個無引數方法
- 可以設定一個預設值
- 推薦把最常用的引數命名為
value
eg:
public @interface Report {
int type() default 0;
String value() default "";
}
1.1.1 元註解
有一些註解可以修飾其他的註解,把這些註解稱為元註解。
1.1.1.1 @Target
註解
使用 @Target
註解可以規定被修飾的註解能應用在原始碼的哪個位置:
ElementType.TYPE
:類或介面ElementType.FIELD
:欄位ElementType.METHOD
:方法ElementType.CONSTRUCTOR
:構造方法ElementType.PARAMETER
:方法引數
eg:
@Target({ ElementType.FIELD, ElementType.METHOD }) public @interface Report { int type() default 0; String value() default ""; }
1.1.1.2 @Retention
註解
@Retention
用於定義被修飾註解的生命週期:
RetentionPolicy.SOURCE
:僅編譯期,編譯器在編譯的時候直接丟棄,比如@Override
RetentionPolicy.CLASS
:僅 class 檔案,該註解僅存在 class 檔案中,不會被讀取,有些工具可以處理 class 檔案,這些工具就可以讀取這個註解RetentionPolicy.RUNTIME
:僅執行期,在執行期可以通過程式碼讀取該註解
如果沒有 @Retention
註解,那麼註解本身的生命週期預設為 CLASS
,通常自定義的註解應該都是 RUNTIME
1.1.1.3 Repeatable
註解
Repeatable
註解修飾的註解可以重複註解,比如:
@Repeatable
@Target(ElementType.TYPE`)
public @interface Report {
int type() default 0;
String value() default "";
}
// 重複使用
@Report(type=1)
@Report(type=2)
public class Hello {
}
1.2 處理註解
因為通常寫的程式碼並不涉及到編譯器,class 檔案中的註解也很少會用到,所以這裡處理的註解主要針對的是執行期可以被讀取的註解,也就是 Runtime
型別的註解。
如何讀取 Runtime
的註解?方法是通過 反射。
因為 Annotaion
也是 class
,所有的 Annotation
都繼承自 java.lang,annotation.Annotation
,使用 反射API 就可以獲取這些 Annotation
。
使用 反射API 確定一個 Annotation
(註解)是否存在:
Class.isAnnotationPresent(Class)
Field.isAnnotationPresent(Class)
Method.isAnnotationPresent(Class)
Constructor.isAnnotationPresent(Class)
eg:
Class cls = Person.class;
// 判斷 @Report 是否存在
cls.isAnnotationPresent(Report.class); // 返回布林值
使用 反射API 獲取一個 Annotation
(註解):
Class.getAnnotation(Class)
Field.getAnnotation(Class)
Method.getAnnotation(Class)
Constructor.getAnnotation(Class)
eg:
class cls = Person.class;
Report report = cls.getAnnotion(Report.class); // 如果不存在,返回 null
int type = report.type();
詳情通過反射讀取註解,處理註解的程式碼,可以檢視我的github
獲取方法引數的
Annotation
比較麻煩,因為一般的方法可能有多個引數,同時引數本身也可以有多個註解,此時使用的是Method.getParemterAnnotations()
方法獲取一個Anntation
的二維陣列,第一個維度代表的是引數的個數,第二個維度代表的是每個引數本身自帶的註解個數。