註解目前很是的流行,不少主流框架都支持註解,並且本身編寫代碼的時候也會盡可能的去用註解,一時方便,而是代碼更加簡潔。java
註解的語法比較簡單,除了@符號的使用以外,它基本與Java固有語法一致。Java SE5內置了三種標準註解:數組
@Override,表示當前的方法定義將覆蓋超類中的方法。框架
@Deprecated,使用了註解爲它的元素編譯器將發出警告,由於註解@Deprecated是不同意使用的代碼,被棄用的代碼。ide
@SuppressWarnings,關閉不當編譯器警告信息。ui
上面這三個註解多少咱們都會在寫代碼的時候遇到。Java還提供了4中註解,專門負責新註解的建立。spa
@Targetcode |
表示該註解能夠用於什麼地方,可能的ElementType參數有:繼承 CONSTRUCTOR:構造器的聲明接口 FIELD:域聲明(包括enum實例)ip LOCAL_VARIABLE:局部變量聲明 METHOD:方法聲明 PACKAGE:包聲明 PARAMETER:參數聲明 TYPE:類、接口(包括註解類型)或enum聲明 |
@Retention |
表示須要在什麼級別保存該註解信息。可選的RetentionPolicy參數包括: SOURCE:註解將被編譯器丟棄 CLASS:註解在class文件中可用,但會被VM丟棄 RUNTIME:VM將在運行期間保留註解,所以能夠經過反射機制讀取註解的信息。 |
@Documented |
將註解包含在Javadoc中 |
@Inherited |
容許子類繼承父類中的註解 |
定義一個註解的方式:
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Test { }
除了@符號,註解很像是一個接口。定義註解的時候須要用到元註解,上面用到了@Target和@RetentionPolicy,它們的含義在上面的表格中已近給出。
在註解中通常會有一些元素以表示某些值。註解的元素看起來就像接口的方法,惟一的區別在於能夠爲其制定默認值。沒有元素的註解稱爲標記註解,上面的@Test就是一個標記註解。
註解的可用的類型包括如下幾種:全部基本類型、String、Class、enum、Annotation、以上類型的數組形式。元素不能有不肯定的值,即要麼有默認值,要麼在使用註解的時候提供元素的值。並且元素不能使用null做爲默認值。註解在只有一個元素且該元素的名稱是value的狀況下,在使用註解的時候能夠省略「value=」,直接寫須要的值便可。
下面看一個定義了元素的註解。
@Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface UseCase { public String id(); public String description() default "no description"; }
定義了註解,必然要去使用註解。
public class PasswordUtils { @UseCase(id = 47, description = "Passwords must contain at least one numeric") public boolean validatePassword(String password) { return (password.matches("\\w*\\d\\w*")); } @UseCase(id = 48) public String encryptPassword(String password) { return new StringBuilder(password).reverse().toString(); } }
使用註解最主要的部分在於對註解的處理,那麼就會涉及到註解處理器。
從原理上講,註解處理器就是經過反射機制獲取被檢查方法上的註解信息,而後根據註解元素的值進行特定的處理。
public static void main(String[] args) { List<Integer> useCases = new ArrayList<Integer>(); Collections.addAll(useCases, 47, 48, 49, 50); trackUseCases(useCases, PasswordUtils.class); } public static void trackUseCases(List<Integer> useCases, Class<?> cl) { for (Method m : cl.getDeclaredMethods()) { UseCase uc = m.getAnnotation(UseCase.class); if (uc != null) { System.out.println("Found Use Case:" + uc.id() + " " + uc.description()); useCases.remove(new Integer(uc.id())); } } for (int i : useCases) { System.out.println("Warning: Missing use case-" + i); } }
Found Use Case:47 Passwords must contain at least one numeric
Found Use Case:48 no description
Warning: Missing use case-49
Warning: Missing use case-50
上面的三段代碼結合起來是一個跟蹤項目中用例的簡單例子。