1. 程式人生 > >從入門到精通:讓人又愛又恨的註解(一)

從入門到精通:讓人又愛又恨的註解(一)

註解和其他資訊配置的區別

註解是一種配置,資訊和程式的分離。 從而利用資訊改變程式的流程。 註解和xml,或者properties檔案有相似的作用,但是又不相同。

  • 相同點: 都是為了在程式執行前,設定一些資訊, 執行時給編譯器,給其他客戶程式讀取,進而改變程式的流程。
  • 不同點: xml等配置檔案,修改之後不需要重新編譯java檔案,但是註解本身就編寫在java類檔案中,被jvm讀取,並存放到記憶體中。因此修改之後,需要重新編譯java檔案。

註解能做什麼

從class檔案規範中可以看出,jdk5開始,class檔案已經引入了註解描述片段。站在java虛擬機器的角度來看,class保留和執行時保留的註解已經和java二進位制碼放在了同等的地位。虛擬機器在載入class檔案時,會為註解內容分配空間並進行解析,最終還會為註解和對應的二進位制碼簡歷關聯。儘管這些註解不會被執行,但其對程式碼的說明能力,結合反射技術已經足夠我們做太多的事情。

註解的語法規則

@interface用來宣告一個註解,其中的每一個方法實際上是聲明瞭一個配置引數。方法的名稱就是引數的名稱,返回值型別就是引數的型別。可以通過default來宣告引數的預設值。

且在@interface之前,需要通過元註解來描述該註解的使用範圍(@Target),生命週期(@Retention)及其他@Target用於描述註解的使用範圍(即: 被描述的註解可以用在什麼地方),型別有:
CONSTRUCTORFIELDLOCAL_VARIABLEPACKAGEPARAMETERTYPE
@Retention用於描述註解的生命週期(即:被描述的註解在什麼範圍內有效),其取值有:
SOURCE 在原始檔中有效
CLASS 在class檔案中有效
RUNTIME 在執行時有效

package com.chdsxt.anno;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
public @interface Table {
public String value() default "";//default表示預設值 public String name() default "";//意義上來說 更像是一個屬性 }

public enum RetentionPolicy { SOURCE, CLASS, RUNTIME }
這是一個enum型別,共有三個值,分別是SOURCE,CLASS,RUNTIME
SOURCE代表的是這個Annotation型別的資訊只會保留在程式原始碼裡,原始碼如果經過了編譯之後,Annotation的資料就會消失,並不會保留在編譯好的.class檔案裡面。
CLASS的意思是這個Annotation型別的資訊只會保留在程式原始碼裡,同時也會保留在編譯好的.class檔案裡面,在執行的時候,並不會把這些資訊載入到虛擬機器中去,注意: 當你沒有設定一個Annotation型別的Retention值時,系統預設值是CLASS。
第三個是, 是RUNTIME,表示在原始碼,編譯好的.class檔案中保留資訊,在執行的時候會把這些資訊載入到jvm中去的。

元註解

public enum RetentionPolicy { SOURCE, CLASS, RUNTIME }

這是一個enum型別,共有三個值,分別是SOURCE,CLASS,RUNTIME
SOURCE代表的是這個Annotation型別的資訊只會保留在程式原始碼裡,原始碼如果經過了編譯之後,Annotation的資料就會消失,並不會保留在編譯好的.class檔案裡面。
CLASS的意思是這個Annotation型別的資訊只會保留在程式原始碼裡,同時也會保留在編譯好的.class檔案裡面,在執行的時候,並不會把這些資訊載入到虛擬機器中去,注意: 當你沒有設定一個Annotation型別的Retention值時,系統預設值是CLASS。
第三個是, 是RUNTIME,表示在原始碼,編譯好的.class檔案中保留資訊,在執行的時候會把這些資訊載入到jvm中去的。

public  enum ElementType  {TYPE, FIELD ,METHOD ,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE ,PACKAGE}

這個用來表示註解的型別,就是可以放置的地方
注意: 如果一個Annotation型別沒有指名@Target使用在哪些元素上,那麼它可以使用在任何元素之上,這裡的元素指的是上面的七種型別。
TYPE: 用於描述類或者介面
Field: 用於描述類的屬性
Method: 用於描述類的方法
Parameter: 用於描述方法的引數
Constructor: 用於描述構造器
Local_variable: 用於描述區域性變數
Package: 用於描述包

另外,在定義個自定義註解的時候,,有兩個元註解的需要特殊注意的。
@Documented讓這個Annotation型別的資訊能夠顯示在javaapi說明文件上; 沒有新增的話,使用javadoc生成api文件的時候就會找不到這個型別生成的資訊。
@Inherited 如果需要把Annotation的資料繼承給子類,那麼就會用到@Inherited