1. 程式人生 > >《java程式設計思想》第二十章 註解

《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作為其值。

 

註解不支援繼承。