Java Annotation 註解

百聯達發表於2016-12-06
一:背景

JDK 5中引入了原始碼中的註解(annotation)這一機制。註解使得Java原始碼中不但可以包含功能性的實現程式碼,還可以新增後設資料。註解的功能類似於程式碼中的註釋,所不同的是註解不是提供程式碼功能的說明,而是實現程式功能的重要組成部分。Java註解已經在很多框架中得到了廣泛的使用,用來簡化程式中的配置。

Java註解是附加在程式碼中的一些元資訊,用於一些工具在編譯、執行時進行解析和使用,起到說明、配置的功能。註解不會也不能影響程式碼的實際邏輯,僅僅起到輔助性的作用。包含在 java.lang.annotation 包中.

二:簡介

a.Annotation與interface的異同:

1)、Annotation型別使用關鍵字@interface而不是interface。


這個關鍵字宣告隱含了一個資訊:它是繼承了java.lang.annotation.Annotation介面,並非宣告瞭一個interface


2)、Annotation型別、方法定義是獨特的、受限制的。


Annotation型別的方法必須宣告為無引數、無異常丟擲的。這些方法定義了annotation的成員:方法名成為了成員名,而方法返回值成為了成員的型別。


方法返回值型別必須為primitive型別、Class型別、列舉型別、annotation型別或者由前面型別之一作為元素的一維陣列。


方法的後面可以使用DEFAULT和一個預設數值來宣告成員的預設值,NULL不能作為成員預設值,這與我們在非annotation型別中定義方法有很大不同。


Annotation型別和它的方法不能使用annotation型別的引數、成員不能是generic。只有返回值型別是Class的方法可以在annotation型別中使用generic,


因為此方法能夠用類轉換將各種型別轉換為Class。


3)、Annotation型別又與介面有著近似之處


它們可以定義常量、靜態成員型別(比如列舉型別定義)。Annotation型別也可以如介面一般被實現或者繼承。


b.註解分類

1 、標準 Annotation
包括Override, Deprecated, SuppressWarnings,標準 Annotation 是指 Java 自帶的幾個 Annotation,上面三個分別表示重寫函式,函式已經被禁止使用,忽略某項 Warning


(1)、Override
  java.lang.Override是一個markerannotation型別,它被用作標註方法。它說明了被標註的方法過載了父類的方法,起到了斷言的作用。如果我們使用了這種annotation在一個沒有覆蓋父類方法的方法時,java編譯器將以一個編譯錯誤來警示。這個annotaton常常在我們試圖覆蓋父類方法而確又寫錯了方法名時加一個保障性的校驗過程。
(2)、Deprecated
  Deprecated也是一種markerannotation。當一個型別或者型別成員使用@Deprecated修飾的話,編譯器將不鼓勵使用這個被標註的程式元素。所以使用這種修飾具有一定的“延續性”:如果我們在程式碼中透過繼承或者覆蓋的方式使用了這個過時的型別或者成員,雖然繼承或者覆蓋後的型別或者成員並不是被宣告為@Deprecated,但編譯器仍然要報警。
注意:@Deprecated這個annotation型別和javadoc中的@deprecated這個tag是有區別的:前者是java編譯器識別的,而後者是被javadoc工具所識別用來生成文件(包含程式成員為什麼已經過時、它應當如何被禁止或者替代的描述)。
(3)、SuppressWarnings
  此註解能告訴Java編譯器關閉對類、方法及成員變數的警告。
  有時編譯時會提出一些警告,對於這些警告有的隱藏著Bug,有的是無法避免的,對於某些不想看到的警告資訊,可以透過這個註解來遮蔽。
        SuppressWarning不是一個markerannotation。它有一個型別為STRING[]的成員,這個成員的值為被禁止的警告名。對於javac編譯器來講,被-Xlint選項有效的警告名也同樣對@SuppressWarings有效,同時編譯器忽略掉無法識別的警告名。annotation語法允許在annotation名後跟括號,括號中是使用逗號分割的NAME=VALUE對用於為annotation的成員賦值:
@SuppressWarnings(VALUE={"unchecked","fallthrough"})
public void lintTrap() { /* sloppy method body omitted */ }

2.元註解是指註解的註解。包括  @Retention @Target @Document @Inherited四種。

@Retention 定義註解的保留策略
 

@Retention(RetentionPolicy.SOURCE)    //註解僅存在於原始碼中,在class位元組碼檔案中不包含
@Retention(RetentionPolicy.CLASS)  // 預設的保留策略,註解會在class位元組碼檔案中存在,但執行時無法獲得,
@Retention(RetentionPolicy.RUNTIME)   // 註解會在class位元組碼檔案中存在,在執行時可以透過反射獲取到

@Target:定義註解的作用目標

@Target(ElementType.TYPE) // 介面、類、列舉、註解
@Target(ElementType.FIELD)  // 欄位、列舉的常量
@Target(ElementType.METHOD)  // 方法
@Target(ElementType.PARAMETER)  // 方法引數
@Target(ElementType.CONSTRUCTOR)   // 建構函式
@Target(ElementType.LOCAL_VARIABLE) // 區域性變數
@Target(ElementType.PACKAGE) / // 包

@Document:說明該註解將被包含在javadoc中
@Inherited:說明子類可以繼承父類中的該註解

3.自定義 Annotation

自定義 Annotation 表示自己根據需要定義的 Annotation,定義時需要用到上面的元 Annotation


三:使用

在一般的Java開發中,最常接觸到的可能就是@Override和@SupressWarnings這兩個註解了。使用@Override的時候只需要一個簡單的宣告即可。這種稱為標記註解(marker annotation ),它的出現就代表了某種配置語義。而其它的註解是可以有自己的配置引數的。配置引數以名值對的方式出現。使用 @SupressWarnings的時候需要類似@SupressWarnings({"uncheck", "unused"})這樣的語法。在括號裡面的是該註解可供配置的值。由於這個註解只有一個配置引數,該引數的名稱預設為VALUE,並且可以省略。而花括號則表示是陣列型別。在JPA中的@Table註解使用類似@Table(NAME = "Customer", SCHEMA = "APP")這樣的語法。從這裡可以看到名值對的用法。在使用註解時候的配置引數的值必須是編譯時刻的常量。

從某種角度來說,可以把註解看成是一個XML元素,該元素可以有不同的預定義的屬性。而屬性的值是可以在宣告該元素的時候自行指定的。在程式碼中使用註解,就相當於把一部分後設資料從XML檔案移到了程式碼本身之中,在一個地方管理和維護。

四:開發

點選(此處)摺疊或開啟

  1. @Target(ElementType.METHOD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface BusinessCheckPoint {

  5.     /**
  6.      * TODO: 業務檢查點名稱
  7.      *
  8.      * @return
  9.      */
  10.     String checkName() default StringUtils.EMPTY;

  11.     /**
  12.      * TODO: 業務型別
  13.      *
  14.      * @return
  15.      */
  16.     String creditCheckName() default StringUtils.EMPTY;

  17. }
@interface用來宣告一個註解,其中的每一個方法實際上是宣告瞭一個配置引數。方法的名稱就是引數的名稱,返回值型別就是引數的型別。可以透過default來宣告引數的預設值。在這裡可以看到這樣的元註解,用來宣告註解本身的行為。@Retention用來宣告註解的保留策略,有這三種,分別表示註解儲存在類檔案、JVM執行時刻和原始碼中。只有當宣告為RUNTIME的時候,才能夠在執行時刻透過反射API來獲取到註解的資訊。@Target用來宣告註解可以被新增在哪些型別的元素上,如型別、方法和域等


五:處理

利用JAVA類的反射機制

點選(此處)摺疊或開啟

  1. method.getAnnotation(AnnotationName.class);
  2. method.getAnnotations();
  3. method.isAnnotationPresent(AnnotationName.class);

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28624388/viewspace-2129869/,如需轉載,請註明出處,否則將追究法律責任。

相關文章