《java程式設計思想》第二十章 註解
JavaSE5內建了三種標準註解,定義在java.lang中的註解:
@Override,表示當前的方法定義將覆蓋超類中的方法。如果沒有重寫,編譯器會發出錯誤提示。
@Deprecated,如果程式設計師使用了該註解註解過的元素,那麼編譯器會發出警告資訊。
@SuppressWarnings,關閉不當的編譯器警告資訊。
元註解是負責註解其他的註解,有四種元註解:
@Target 表示該註解可以用於什麼地方。可能的ElementType(列舉)引數包括:
CONSTRUCTOR:構造方法宣告
FIELD:域宣告(包括enum例項)
LOCAL_VARIABLE:區域性變數宣告
METHOD:方法宣告
PACKAGE:包宣告
PARAMETER:引數宣告
TYPE:類,介面(包括註解型別)或enum宣告
@Retention 表示需要在什麼級別儲存註解資訊。可用的RetentionPolicy(列舉)引數包括:
SOURCE:註解將被編譯地器丟棄。
CLASS:註解在class檔案中可用,但會被VM丟棄。
RUNTIME:VM將在執行期也保留註解,因此可以通過反射機制讀取註解的資訊。
@Documented 將此註解包含在JavaDoc中。
@Inherited 允許子類繼承父類中的註解。
Class、Method、Field、Constructor類都實現了AnnotatedElement介面,他們的getAnnotation方法都返回指定型別的註解物件,如果沒有該型別的註解,則返回null值,以下是這些方法的原型:
class. getAnnotation(Class<T> annotationClass)
method. getAnnotation(Class<T> annotationClass)
field. getAnnotation(Class<T> annotationClass)
constructor. getAnnotation(Class<T> annotationClass)
註解的定義看起來很像介面的定義,事實上,與其他任何Java介面一樣,註解也會編譯成class檔案。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/*
* 這是一個簡單的註解,我們可以用它來跟蹤一個專案中的用例。如果一個方法
* 或一組方法實現了某個用例的需求,那麼程式設計師可以為此方法加上該註解。
*/
//註解的定義
@Target(ElementType.METHOD)//該註解用於方法
@Retention(RetentionPolicy.RUNTIME)//註解資訊保留到執行期
public @interface UseCase {
public int id();//int型的元素
public String description() default "no description";//String型的元素
}
//註解的使用
class PasswordUtils {
@UseCase(id = 47, description = "密碼必須至少包含一個數字")
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();
}
@UseCase(id = 49, description = "新密碼不能使用以前使用過的密碼")
public boolean checkForNewPassword(
List<String> prevPasswords, String password) {
return !prevPasswords.contains(password);
}
}
//註解處理器
class UseCaseTracker {
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("找到用例:" + uc.id() +
" " + uc.description());
useCases.remove(new Integer(uc.id()));
}
}
for(int i : useCases) {
System.out.println("警告: 所缺用例-" + i);
}
}
public static void main(String[] args) {
List<Integer> useCases = new ArrayList<Integer>();
Collections.addAll(useCases, 47, 48, 49, 50);
trackUseCases(useCases, PasswordUtils.class);
}
}
/*
找到用例:47 密碼必須至少包含一個數字
找到用例:48 no description
找到用例:49 新密碼不能使用以前使用過的密碼
警告: 所缺用例-50
*/
註解裡的組成元素型別:
1、 所有基本型別
2、 String
3、 Class
4、 enum
5、 Annotation
6、 以上型別的陣列
如果你使用了其他型別,那編譯器就會報錯。
註解組成元素的預設值限制:首先,元素不能有不確定的值,也就是說,元素必須要麼具有預設值,要麼在使用註解時提供元素的值,不允許即沒給定預設值,在使用進也沒指定值的情況出現。其次,對於非基本型別的元素,無論是在宣告還是在使用時,都不能以null作為其值。
註解不支援繼承。