標籤:產生 java 檔案 ted 預設值 create cti 響應 trace
Annotation 被稱為註解,在Java開發中是相當常見的,通過註解,我們可以簡化代碼提高開發效率。例如Override Annotation,這個應該算是在開發過程中使用最多的註解了。下面這個例子是Android Activity的onCreate方法最常用的註解:
@Overridepublic void onCreate(Bundle savedInstanceState);
1.Annotation 概念
An annotation is a form of metadata, that can be added to Java source code. Classes, methods, variables, parameters and packages may be annotated. Annotations have no direct effect on the operation of the code they annotate.
譯文:
Annotation (註解) 表示的是能夠添加到Java原始碼的文法中繼資料。類、方法、變數、參數、包都可以被註解,可用來將資訊中繼資料和程式元素進行關聯。
2.Annotation 作用
a.標記作用,用於告訴編譯器一些資訊
b.編譯時間動態處理,如動態產生代碼
c.運行時動態處理,如得到註解資訊
這三個作用對應著後面自訂Annotation時說的@Retention三種值分別表示的Annotation
3.Annotation 分類a.標準 Annotation
包括 Override, Deprecated, SuppressWarnings,標準 Annotation 是指 Java 內建的幾個 Annotation,上面三個分別表示重寫函數,不鼓勵使用(有更好方式、使用有風險或已不在維護),忽略某項 Warning
b.元 Annotation
@Retention, @Target, @Inherited, @Documented,元 Annotation 是指用來定義 Annotation 的 Annotation。
—@Documented:是否會儲存到 Javadoc 文檔中
—@Retention:保留時間,可選值 SOURCE(源碼時),CLASS(編譯時間),RUNTIME(運行時),預設為 CLASS,值為 SOURCE 大都為 Mark Annotation,這類 Annotation 大都用來校正,比如 Override, Deprecated, SuppressWarnings
—@Target:可以用來修飾哪些程式元素,如 TYPE, METHOD, CONSTRUCTOR, FIELD, PARAMETER 等,未標註則表示可修飾所有。
—@Inherited: 是否可以被繼承,預設為 false
c.自訂 Annotation
自訂 Annotation 表示自己根據需要定義的 Annotation,定義時需要用到上面的元 Annotation,這裡只是一種分類而已,也可以根據範圍分為源碼時、編譯時間、運行時 Annotation。
4.Annotation 自訂
a.定義
下面實現了一個自訂註解—MethodInfo:
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Inheritedpublic @interface MethodInfo { String author() default "renhui"; String date(); int version() default 1;}
這裡是 的實現部分
(1). 通過 @interface 定義,註解名即為自訂註解名
(2). 註解配置參數名為註解類的方法名,且:
a. 所有方法沒有方法體,沒有參數沒有修飾符,實際只允許 public & abstract 修飾符,預設為 public ,不允許拋異常
b. 方法傳回值只能是基本類型,String, Class, annotation, enumeration 或者是他們的一維數組
c. 若只有一個預設屬性,可直接用 value() 函數。一個屬性都沒有表示該 Annotation 為 Mark Annotation
(3). 可以加 default 表示預設值
b.調用
public class App { @MethodInfo( author = “renhui”, date = "2016/01/14", version = 1) public String getAppName() { return "demo"; }}
這裡是調用自訂 Annotation——MethodInfo 的樣本,MethodInfo Annotation 作用為給方法添加相關資訊,包括 author、date、version
c.解析
運行時 Annotation 解析
(1) 運行時 Annotation 指 @Retention 為 RUNTIME 的 Annotation,可手動調用下面常用 API 解析
method.getAnnotation(AnnotationName.class);method.getAnnotations();method.isAnnotationPresent(AnnotationName.class);
其他 @Target 如 Field,Class 方法類似
getAnnotation(AnnotationName.class) 表示得到該 Target 某個 Annotation 的資訊,因為一個 Target 可以被多個 Annotation 修飾
getAnnotations() 則表示得到該 Target 所有 Annotation
isAnnotationPresent(AnnotationName.class) 表示該 Target 是否被某個 Annotation 修飾
(2) 解析樣本如下:
public static void main(String[] args) { try { Class cls = Class.forName("*.App"); for (Method method : cls.getMethods()) { MethodInfo methodInfo = method.getAnnotation(MethodInfo.class); if (methodInfo != null) { System.out.println("method name:" + method.getName()); System.out.println("method author:" + methodInfo.author()); System.out.println("method version:" + methodInfo.version()); System.out.println("method date:" + methodInfo.date()); } } } catch (ClassNotFoundException e) { e.printStackTrace(); }}以之前自訂的 MethodInfo 為例,利用 Target(這裡是 Method)getAnnotation 函數得到 Annotation 資訊,然後就可以調用 Annotation 的方法得到響應屬性值編譯時間 Annotation 解析
(1) 編譯時間 Annotation 指 @Retention 為 CLASS 的 Annotation,甴 apt(Annotation Processing Tool) 解析自動解析。需要做的
a. 自訂類整合自 AbstractProcessor
b. 重寫其中的 process 函數
這塊很多同學不理解,實際是 apt(Annotation Processing Tool) 在編譯時間自動尋找所有繼承自 AbstractProcessor 的類,然後調用他們的 process 方法去處理
(2) 假設之前自訂的 MethodInfo 的 @Retention 為 CLASS,解析樣本如下:
@SupportedAnnotationTypes({ "*.MethodInfo" })public class MethodInfoProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) { HashMap<String, String> map = new HashMap<String, String>(); for (TypeElement te : annotations) { for (Element element : env.getElementsAnnotatedWith(te)) { MethodInfo methodInfo = element.getAnnotation(MethodInfo.class); map.put(element.getEnclosingElement().toString(), methodInfo.author()); } } return false; }}
SupportedAnnotationTypes 表示這個 Processor 要處理的 Annotation 名字。
process 函數中參數 annotations 表示待處理的 Annotations,參數 env 表示當前或是之前的運行環境
process 函數傳回值表示這組 annotations 是否被這個 Processor 接受,如果接受後續子的 rocessor 不會再對這個 Annotations 進行處理
使用編譯時間註解很實用的例子:做代碼混淆時可以通過添加編譯時間註解並配合設定檔,達到指定的類、方法、對象等不進行混淆
Java Annotation 總結