以下內容參考java編程思想-4,jdk版本為jdk5.0,有點老-_-||| 什麼是註解 JAVA SE5引入,也稱元數據,可以直接添加到代碼中,用來完整描述程式所需的信息,而這些信息是無法用Java來表達的; 內置註解 jdk5.0中內置了三種標準註解和四種元註解; 三種標準註解,定義在java ...
以下內容參考java編程思想-4,jdk版本為jdk5.0,有點老-_-|||
什麼是註解
JAVA SE5引入,也稱元數據,可以直接添加到代碼中,用來完整描述程式所需的信息,而這些信息是無法用Java來表達的;
內置註解
jdk5.0中內置了三種標準註解和四種元註解;
三種標準註解,定義在java.lang中:
@Override //表示子類方法覆蓋父類方法
@Deprecated //已過時,不建議使用的API
@SuppressWarnings //取消編譯器警告
四種元註解:
@Target //指定該註解可以用在什麼地方
可選參數:
CONSTRUCTOR:構造器聲明
FIELD:域聲明
LOCAL_VARIABLE:局部變數聲明
METHOD:方法聲明
PACKAGE:包聲明
PARAMETER:參數聲明
TYPE:類、介面聲明
@Retention //表明該註解在哪一級別可用
可選參數:
SOURCE:註解將被編譯器丟棄;
CLASS:註解在class文件中可用,但會被VM丟棄;
RUNTIME:VM在運行期間也保留註解,可以通過反射機制讀取註解信息;
@Documented//表明將此註解包含在Javadoc中
@Inherited //允許子類繼承父類的註解
基本語法
自定義註解
標記註解
定義一個@Test註解,如下代碼所示,可以看到,註解的定義與介面類似,事實上註解與介面一樣,也會被編譯成class文件;
package annotations; import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Test { }
在註解中,一般都會包含一些元素以表示某些值,當分析處理註解時,程式可以讀取這些值;
上面的@Test註解不包含元素,被稱為標記註解;
包含元素的註解
下麵代碼定義了一個包含元素的註解,元素的定義類似於方法,定義中包含了元素的數據類型,如下,id為int類型,description為String類型,且包含一個預設值;
package annotations; import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface UseCase { public int id(); public String description() default "no description"; }
註意,註解元素可用的類型如下:
所有的基本數據類型(int,double...)
String
Class
enum
Annotation
數組(以上類型為元素)
如果使用其它類型編譯器會報錯,特別提醒,Integer,Double等基本數據類型的包裝類型也是不允許的;
另外,元素是不能有不確定的值,要麼有預設值,要麼提供元素的值,且不能為null;
註解使用
上面定義的@UseCase註解的使用如下所示,很簡單,在方法前面寫上註解,並指定元素的值,如果未指定的話將使用預設值;
package annotations; import java.util.*; 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> prevPasswords, String password) { return !prevPasswords.contains(password); } }
編寫註解處理器
利用JAVA的反射機制,可以查找註解標記,下麵是一個簡單的註解處理器,用於解析上面提到的@UserCase註解,主要使用到了Class類的getDeclaredMethods()方法和Method類的getAnnotation(Class<T> annotationClass)方法;getDeclaredMethods返回類中聲明的所有方法,getAnnotation返回指定的註解;
package annotations; import java.lang.reflect.*; import java.util.*; public 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("Found Use Case:" + uc.id() + " " + uc.description()); useCases.remove(new Integer(uc.id())); } } for (int i : useCases) { System.out.println("Warning: Missing use case-" + i); } } public static void main(String[] args) { List<Integer> useCases = new ArrayList<Integer>(); Collections.addAll(useCases, 47, 48, 49, 50); trackUseCases(useCases, PasswordUtils.class); } }
註解常見使用場景
描述資料庫表結構與類關係映射(hibernate...)
單元測試(junit...)
一些配置等(spring...)
...