Documented
這個注釋(Annotation)將作為public API的一部分
Inherited
假設注釋(Annotation)定義的時候使用了Inherited
那麼如果這個注釋(Annotation)修飾某個class
這個類的子類也被這個注釋(Annotation)所修飾
注釋的應用
下面各小節顯示了在哪些情況下可以使用注釋以及如何使用注釋
動態查找注釋
當我們定義好了注釋以後
我們可以開發一些分析工具來解釋這些注釋
這裡通常要用到Java的反射特性
比如說我們希望找到某個對象/方法/域使用了哪些注釋
或者獲得某個特定的注釋
或者判斷是否使用某個特定的注釋
我們可以參考下面這個例子
這個例子中定義了兩個注釋
TODO和TOFORMATE
在MyCalculator類中
TODO用來修飾方法calculateRate
而TOFORMATE用來修飾類變量concurrency和debitDate
而在類TestCalculator的main函數中
通過Java反射特性
我們查找到使用這些注釋的類變量和方法
清單
清單
分別顯示這些類的定義
清單
TODO注釋的定義
@Target({ElementType
METHOD})
@Retention(RetentionPolicy
RUNTIME)
public @interface TODO {
int priority() default
;
}
清單
TOFORMATE的定義
@Target({ElementType
FIELD})
@Retention(RetentionPolicy
RUNTIME)
public @interface TOFORMATE {
}
清單
使用注釋的類MyCalculator
public class MyCalculator {
boolean isReady;
@TOFORMATE double concurrency;
@TOFORMATE Date debitDate;
public MyCalculator() {
super();
}
@TODO
public void calculateRate(){
System
out
println(
Calculating
);
}
}
清單
動態查找注釋
public class TestCalculator {
public static void main(String[] args) {
MyCalculator cal = new MyCalculator();
cal
calculateRate();
try {
Class c = cal
getClass();
Method[] methods = c
getDeclaredMethods();
for (Method m: methods) {
// 判斷這個方法有沒有使用TODO
if (m
isAnnotationPresent(TODO
class))
System
out
println(
Method
+m
getName()+
: the TODO is present
);
}
Field[] fields = c
getDeclaredFields();
for (Field f : fields) {
// 判斷這個域有沒有使用TOFORMATE
if (f
isAnnotationPresent(TOFORMATE
class))
System
out
println
(
Field
+f
getName()+
: the TOFORMATE is present
);
}
} catch (Exception exc) {
exc
printStackTrace();
}
}
}
下面我們來運行這個例子
這個例子的運行結果如圖
所示
運行結果和我們先前的定義是一致的
在運行時
我們可以獲得注釋使用的相關信息
圖 運行結果 在我們介紹了什麼是注釋以後
你可能會想知道注釋可以應用到什麼地方呢?使用注釋有什麼好處呢?在下面的小節中我們將介紹一個稍復雜的例子
從這個例子中
你將體會到注釋所以提供的強大的描述機制(declarative programming)
使用注釋替代Visitor模式
在J
SE
以前
我們在設計應用的時候
我們經常會使用Visitor這個設計模式
Visitor這個模式一般是用於為我們已經設計好了一組類添加方法
而不需要擔心改變定義好的類
比如說我們已經定義了好了一組類結構
但是我們希望將這些類的對象部分數據輸出到某種格式的文件中
Vistor模式的實現
使用Vistor模式
首先我們在Employee這個類中加入export方法
export方法如圖
所示
Export方法接受Exporter對象作為參數
並在方法體中調用exporter對象的visit()方法
圖 使用Vistor模式實現格式輸出 在這裡我們定義了一個Exporter抽象類
我們可以通過繼承Exporter類
重寫其visit方法來實現不同格式的文件輸出
圖
種給出visit方法的實現是一個簡單的例子
如果要實現輸出成XML格式的
可以定義Exporter子類
XMLExporter
如果希望輸出成文本的可以定義TXTExporter
但是這樣做不夠靈活的地方在於
如果Employee加入其他的域變量
那麼相應的visitor類也需要進行修改
這就違反了面向對象Open for Extension
close for Modification的原則
使用注釋替代Vistor模式
使用注釋(Annotation)
也可以完成數據輸出的功能
首先定義一個新的注釋類型
@Exportable
然後定義一個抽象的解釋器ExportableGenerator
將Employee 對象傳入解釋器
在解釋器中
查找哪些域使用了Exportable這個注釋(Annotation)
將這些域(Field)按照一定格式輸出
圖
給出了Exportable注釋的定義
清單
注釋Exportable的定義
@Target({ElementType
FIELD})
@Retention(RetentionPolicy
RUNTIME)
@Inherited
public @interface Exportable {
}
清單
清單
中給出了包含數據的這些類的定義以及這些類是如何使用注釋Exportable的
圖
定義了Main函數
使用ExporterGenerator來產生輸出文件
清單
給出了使用注釋來實現這一功能的兩個類
ExporterGenerator和TXTExporterGenerator
其中ExporterGenerator定義了一個基本的框架
而TXTExporterGenerator繼承了ExporterGenerator
並且重寫了outputField方法
在這個方法中實現了特定格式的輸出
用戶可以繼承這個ExporterGenerator
並且實現其中的抽象方法來定義自己期望的格式
清單
Employee的類定義
public abstract class Employee {
public abstract String getName();
public abstract String getEmpNo();
public Employee() {
super();
}
}
清單
Regular的類定義
public class Regular extends Employee{
@Exportable String name;
@Exportable String address;
@Exportable String title;
@Exportable String phone;
@Exportable String location;
@Exportable Date onboardDate;
@Exportable ArrayList team;
String empNo;
public Regular(String name
String address
String title
String phone
String location
Date date) {
super();
this
name = name;
this
address = address;
this
title = title;
this
phone = phone;
this
location = location;
onboardDate = date;
team = new ArrayList();
}
public void addMemeber(Employee e){
team
add(e);
}
@Override
public String getName() {
// TODO Auto
generated method stub
return name;
}
}
From:http://tw.wingwit.com/Article/program/Java/ky/201311/27990.html