閱讀842 返回首頁    go 阿裏雲 go 技術社區[雲棲]


Java Annotation學習筆記

作為一個早期短暫從事過C++開發工作的程序員,我個人認為Annotation可能是Java與C++語言較大的不同點之一,這也是一個前C++程序員由衷認為Java可能、或許、maybe要比C++更好用的原因之一。二十多年來,Java一直保持著更新,不斷完善並與時俱進,這可能是其多年來獨領編程語言之風騷的重要原因。不多扯,入正題。(編程知識的學習,我一般會遵循這樣的一個過程:先熟悉基本概念,再來個小程序跑起來看看,最後理論與程序相結合,加深認識並總結記錄。)

1、什麼是Annotation


Annotation被譯作“注解”,標準的英譯漢,但是這個譯詞並沒有很好的反映Annotation在java中的意義,或許“標記”更好一些,也或許“標簽”。

注解(也被稱為元數據)為我們在代碼中添加信息提供了一種形式化的方法,使我們可以在稍後的某個時刻非常方便地使用這些數據。——《Java編程思想》

注解是那些插入到源代碼中使用其他工具可以對其進行處理的標簽。——《Java核心技術卷2》

從《Java核心技術卷2》的定義來看,注解包含兩點內容:其一,它是標簽、標記;此外,這個標簽(標記)可以使用其他工具進行處理。
那麼,其他工具在哪裏可以處理這些標簽呢?一個是源碼層,另一個是類文件。

注解不會改變程序的編譯方式,對於包含注解和不包含注解的代碼,Java編譯器會生成相同的虛擬機指令。——《Java核心技術卷2》

綜上,大致可以給出Java注解一個簡單通俗的描述使用過程:定義標簽,然後提供標簽處理工具,最後是應用標簽到其它的代碼中。當然,Java自帶的注解,我們就隻需要直接使用就可以了,因為定義和處理工具Java都幫我們做好了。

2、來個sample


2.1定義標簽

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface UseCase {

    public int id();

    public String description() default "No description";
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
Target和Retention是java語言自帶的兩個元注解,Target表示用戶自定義的注解(UseCase)能應用在哪裏(注解類型聲明,包,類或接口、方法等);
Retention用來指明自定義注解應該保留多長的時間(取值為SOURCE/CLASS/RUNTIME)
public @interface UseCase
這是定義注解的語法形式,乍一看類似接口的定義,區別在於interface前加了一個@符號,後續使用該用戶自定義注解時語法就是@UseCase
public int id();
public String description() default "No description";
這是注解中定義字段的語法,()並不表示這是一個方法,再者,注解中不支持定義方法。
同時,可以設置字段的默認值,通過default關鍵字。沒有默認值的字段必須在使用時顯示指明。

2.2 標簽處理工具

import java.lang.reflect.*;

public class UseCaseTracker {

    public static void trackUseCase(Class<?> cl) {
        for (Method m : cl.getMethods()) {
            UseCase useCase = m.getAnnotation(UseCase.class);
            if (useCase != null) {
                System.out.println("Found Use Case : " + useCase.id() + " " + useCase.description());
            }
        }
    }

}
@Retention(RetentionPolicy.RUNTIME)中的RUNTIME使得注解可以保留到類文件中,並由虛擬機載入,這樣我們就可以通過反射API來獲得它們。接下來我就是通過反射API獲得這些注解。
public static void trackUseCase(Class<?> cl) {
    for (Method m : cl.getMethods()) {
        UseCase useCase = m.getAnnotation(UseCase.class);
        if (useCase != null) {
            System.out.println("Found Use Case : " + useCase.id() + " " + useCase.description());
        }
    }
}
trackUseCase方法通過傳入應用了UseCase注解的類,再通過反射API獲得這些注解並打印注解中的信息。 

2.3 應用標簽

import java.util.List;

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();
    }

    @UseCase(id=49, description="New passwords can't equal previously used ones")
    public boolean checkForNewPassword(List<String> prePasswords, String password) {
        return !prePasswords.contains(password);
    }

}
@Target(ElementType.METHOD)規定了注解隻能是應用在方法上,因此,上述例子中便是如此。
@UseCase(id=47, description="Passwords must contain at least one numeric")
@UseCase(id=48)
@UseCase(id=49, description="New passwords can't equal previously used ones")
以上是三種使用應用自定義注解的例子。

2.4 測試

import java.lang.reflect.*;

public class UseCaseTracker {

    public static void trackUseCase(Class<?> cl) {
        for (Method m : cl.getMethods()) {
            UseCase useCase = m.getAnnotation(UseCase.class);
            if (useCase != null) {
                System.out.println("Found Use Case : " + useCase.id() + " " + useCase.description());
            }
        }
    }

    public static void main(String[] args) {
        trackUseCase(PasswordUtils.class);
    }

} 

直接在注解處理工具中加了個main方法來測試注解處理工具。輸出結果如下:

Found Use Case : 47 Passwords must contain at least one numeric
Found Use Case : 49 New passwords can't equal previously used ones
Found Use Case : 48 No description

注:以上代碼來自《Java編程思想》,部分有改動。

3、歸納整理


3.1 注解元素(屬性)的類型

基本類型(int/short/long/byte/char/double/float/boolean)
String
Class
enum
注解類型
以上五種類型組成的數組

注:注解元素值不能為null,默認值也不能為null。

3.2 標準注解

這裏寫圖片描述

3.3 Target注解的元素類型

元素類型定義在枚舉類星Element中。
這裏寫圖片描述

3.4 Retention注解的元素類型

這裏寫圖片描述

最後更新:2017-07-02 21:32:27

  上一篇:go  關於音遊,除了節奏大師,你還熟悉哪些?
  下一篇:go  講講 2017年 繞不開的雙攝