一、基本概念
在開發Java程序,尤其是Java EE應用的時候,總是免不了與各種配置文件打交道。以Java EE中典型的S(pring)S(truts)H(ibernate)架構來說,Spring、Struts和Hibernate這三個框架都有自己的XML格式的配置文件。這些配置文件需要與Java源代碼保存同步,否則的話就可能出現錯誤。而且這些錯誤有可能到了運行時刻才被發現。把同一份信息保存在兩個地方,總是個壞的主意。理想的情況是在一個地方維護這些信息就好了。其它部分所需的信息則通過自動的方式來生成。JDK 5中引入了源代碼中的註解(annotation)這一機制。註解使得Java源代碼中不但可以包含功能性的實現代碼,還可以添加元數據。註解的功能類似於代碼中的註釋,所不同的是註解不是提供代碼功能的說明,而是實現程序功能的重要組成部分。Java註解已經在很多框架中得到了廣泛的使用,用來簡化程序中的配置。
二、常用的Java內置註解
Java中常用的內置註解是以下三種:
- @Override:表示當前方法將重寫父類的相同簽名的方法;
- @Deprecated:表示該類或者方法是不建議被使用的,當用戶使用時編譯器會給出警告;
- @SuppressWarnings:表示暫時關閉指定的編譯器警告。
三、自定義註解
自定義註解的定義與接口定義相似,當註解定義後也會被編譯爲class文件。
定義自己的註解需要用到Java提供的元註解去修飾自定義註解:
@Target:表示該自定義註解所適用的程序元素的種類(方法,局部變量,類等),省略則表示該註解能應用於所有程序元素,其值爲java.lang.annotation.ElementType枚舉類型:
- TYPE:類、接口或枚舉類型的定義;
- FIELD:成員變量(包括enum實例)的聲明;
- METHOD:方法聲明;
- PARAMETER:方法參數聲明;
- CONSTRUCTOR:構造函數聲明;
- LOCAL_VARIABLE:局部變量聲明;
- ANNOTATION_TYPE:註解的定義;
- PACKAGE:包聲明。
@Retention:表示要在什麼級別保存自定義註解信息,即該自定義註解需要保存多久。其值爲java.lang.annotation.RetentionPolicy枚舉類型:
- SOURCE:自定義的註解信息只會保存在源代碼,當編譯時會被編譯器忽略;
- CLASS:自定義的註解信息會被編譯器保存進class文件,但會在運行時被VM忽略(默認行爲);
- RUNTIME:在CLASS的基礎上,VM同時會在運行時保存註解信息,因此可以通過反射讀取。
@Documented:表示自定義註解需要包含在javadoc中;
@Inherited:表示允許子類繼承父類的自定義註解。
示例一:
package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定義註解@MyAnnotation,能用於方法定義,並能在運行時獲取。
* 註解中有一個屬性value。
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
public String value();
}
package annotation;
import java.lang.reflect.Method;
/**
* 使用自定義的註解
*/
public class AnnotationTest {
//當註解中只有唯一的名叫value的屬性時,可以只寫屬性值傳參
@MyAnnotation("test")
public static void main(String[] args) {
//使用反射獲取main方法的Method對象
Method mainMethod = AnnotationTest.class.getMethods()[0];
//在Method對象上獲取@MyAnnotation註解
MyAnnotation myAnnotation = mainMethod.getAnnotation(MyAnnotation.class);
//獲取註解的value屬性
System.out.println("@MyAnnotation: " + myAnnotation.value());
}
}
輸出:
@MyAnnotation: test
示例二:
package annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* 自定義註解@MyAnnotation,能用於方法定義,並能在運行時獲取。
* 註解中有兩個屬性id和message,message使用default提供默認值。
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
public int id();
public String message() default "None";
}
package annotation;
import java.lang.reflect.Method;
public class AnnotationTest {
//當value不是註解中的唯一屬性時,需要以
//屬性名=屬性值的形式賦值
@MyAnnotation(id = 1)
public static void main(String[] args) {
Method mainMethod = AnnotationTest.class.getMethods()[0];
MyAnnotation testAnnotation = mainMethod.getAnnotation(MyAnnotation.class);
System.out.println("id: " + testAnnotation.id());
//message會輸出默認值None
System.out.println("message: " + testAnnotation.message());
}
}
輸出:
id: 1
message: None