Java Annotation 註解

java_notation.htmljavascript

Java Annotation 註解

註解:

是Java代碼中的元數據, 在建立以後的某個時刻能夠使用, 表明了代碼的配置信息, 代碼和配置結合在一塊兒, 存儲有關程序的額外信息.php

定義註解:

註解的定義相似interface的定義, 同其餘Java接口同樣, 註解也會被編譯成class文件. 格式爲:css

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.Runtime)
public @interface Test{
    ///
    public int id();
    public String descripteion() default "no description";
}

其中, @Target@Retention也是註解被稱爲元註解, 是Java提供的四種註解,後面會補充.
@Target 表明了該註解應用的對象(如一個類或者一個函數).
@Retention 表明了該註解在哪個級別可用(共三種: 源碼中Source, 類文件Class, 運行時Runtime).
通常的註解中會有元素, 元素的定義相似於接口中方法的定義(成員變量相似接口的方法的定義). 可是後面能夠跟一個default指定默認值.
沒有元素的註解稱之爲標記註解, 如元註解中的 @Documented
註解的元素使用時是以名-值對的形式定義的, 並放在註解後的括號內, 如@Test( id = 49, desctiption = "lyb" ).html

元註解:

元註解是Java源碼中定義的四種註解, 本身定義的註解必然要藉助這四種註解.java

註解 解釋
@Target 表示該註解能夠用於什麼地方, 接受的參數爲ElementType參數, 共有如下幾種類型:
CONSTRUCTOR: 構造器的聲明
FIELD: 域聲明(包括enum實例)
LOCAL_VARIABLE: 局部變量聲明
METHOD: 方法聲明
PACKAGE: 包聲明
PARAMETER: 參數聲明
TYPE: 類, 接口(包括註解類型)或enum聲明
@Retention 表示須要在什麼級別保存該註釋信息, 接受參數爲RetentionPolicy類型:
SOURCE: 註解將被編譯器丟棄
CLASS: 註解在class文件中可用,可是會被編譯器丟棄
RUNTIME: VM將在運行期也保留註解, 所以能夠經過反射機制讀取註解的信息
@Documented 將此註解包含在Javadoc中
@Inherited 容許子類繼承父類中的註解

元註解自己的定義也是依賴元註解的, 相似於遞歸.
@Target的源碼:node

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
    /** * Returns an array of the kinds of elements an annotation type * can be applied to. * @return an array of the kinds of elements an annotation type * can be applied to */
    ElementType[] value();
}

註解解釋器:

註解和註釋的區別: 若是沒有處理註解的工具, 那麼註解不會比註釋更有用. 因此使用註解就是要有相應的註解處理器, 而註解處理器是創建在反射機制上的.nginx

對以VM, 在沒有註解處理器的狀況下, 有沒有註解對於源代碼編譯獲得的字節嗎應該是同樣的, 固然可能會多出註解的字節碼.git

下面給出一個例子:github

註解UserCase:web

package test;

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

/** * Created by lyb on 16-11-29. */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UserCase {
    public int id();
    public String description() default "no description";
}

使用了註解的通常類:

package test;

import java.util.List;

/** * Created by lyb on 16-11-29. */
public class PasswordUtil {
    @UserCase(id = 47, description = "Passwords must contains at last one numberic")
    public boolean validatePassword(String password){
        return password.matches("\\w*\\d\\w*");
    }

    @UserCase(id = 48)
    public String encryptPassword(String password){
        return new StringBuilder(password).reverse().toString();
    }

    @UserCase(id = 50, description = "New passwords can't equals the used one")
    public boolean checkForNewPassword(List<String> prevPassword, String password){
        return !prevPassword.contains(password);
    }
}

真正的註解處理器:

package test;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/** * Created by lyb on 16-11-29. */
public class UserCaseTracker {
    public static void trackUserCases(List<Integer> userCases, Class<?> cl){
        for (Method m : cl.getDeclaredMethods()){
            UserCase uc = m.getAnnotation(UserCase.class);
            if (uc != null){
                System.out.println("Found user case : " + uc.id()
                        + " " + uc.description());
                userCases.remove(new Integer(uc.id()));
            }
        }
        for (int i : userCases){
            System.out.println("Warning: Missing user case !");
        }
    }

    public static void main(String[] args){
        List<Integer> userCases = new ArrayList<>();
        Collections.addAll(userCases, 47, 48, 49, 50);
        trackUserCases(userCases, PasswordUtil.class);
    }
}

程序的輸出:

Found user case : 47 Passwords must contains at last one numberic
Found user case : 48 no description
Found user case : 50 New passwords can't equals the used one
Warning: Missing user case-49!

須要注意的地方,

  1. 傳給反射的參數是class類型的.

  2. 由於@UserCase 修飾的是Method, 因此經過Method獲得註解對象.

註解元素的類型:

即在註解的interface中定義的相似函數的元素, 如int的id(), String的description().

全部可用的註解元素的類型有:

  1. 全部基本類型(int, float, boolean)等
  2. String
  3. class
  4. enum
  5. Annotation
  6. 以上類型的數組

須要注意的是:

  1. 不能使用任何包裝類型
  2. 註解能夠嵌套

對註解元素的限制:

註解中的元素都必須肯定, 或者有默認值, 或者在註解中賦值.

非基本類型(如本身定義的類)的值不能有null, 所以必須本身定義一些特殊值來表示某個元素不存在.

使用多個註解的時候, 同一個註解不能重複使用.

註解自己不支持繼承, 可是被 @Inherited 修飾的類具備繼承性. 一樣地, 因爲沒有繼承性, 所以要具備相似多態的註解, 就必須多定義不一樣參數的函數或者是類, 而且用反射函數 getDeclaredAnnotation() 來遍歷獲得須要的註解.

generated by haroopad

相關文章
相關標籤/搜索