java @interface自定義註解和通過反射獲取註解屬性值
阿新 • • 發佈:2019-01-31
@interface
@interface用來宣告一個註解,其中的每一個方法實際上是聲明瞭一個配置引數。
方法的名稱就是引數的名稱,返回值型別就是引數的型別
引數型別只能是基本型別、Class、String、enum。
可以通過default來宣告引數的預設值。
Java註解就是一種特殊的介面,使用@interface自定義註解時,自動繼承了java.lang.annotation.Annotation介面,因此在自定義註解時不能繼承其他的註解或者介面。
註解的應用
- 生成文件。如@param @return 等
- 替代配置檔案功能。如spring2.5開始的基於註解配置。作用就是減少配置。現在的框架基本都使用了這種配置來減少配置檔案的數量
- 在編譯時進行格式檢查。如@Override
自定義註解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ProductAnnotation {
//型別列舉
public enum Type{ 手機,電腦,平板};
//商品型別
Type productType() default Type.手機;
//商品釋出時間
String publishYear() default "";
//商品名稱
String productName() default "";
}
Target 指明該型別的註解可以註解的元素範圍,主要包括以下幾種引數型別:
ElementType.TYPE 用於類,介面,列舉,但不能是註解 ElementType.FIELD 作用於欄位,包含列舉值 ElementType.METHOD 作用於方法,不包含構造方法 ElementType.PARAMETER 作用於方法的引數 ElementType.CONSTRUCTOR 作用於構造方法 ElementType.LOCAL_VERIABLE 作用於本地變數或者catch語句 ElementType.ANNOTATION_TYPE 作用於註解 ElementType.PACKAGE 作用於包
Retention 指明在什麼級別顯示此註解,主要包括以下幾種引數型別:
RetentionPolicy.SOURCE 註解存在於原始碼中,編譯時會被拋棄
RetentionPolicy.CLASS 註解會被編譯到class檔案中,但是JVM會忽略
RetentionPolicy.RUNTIME JVM會讀取註解,同時會儲存到class檔案中
通過反射獲取註解屬性值
註解的解析依賴於反射。jdk1.5 增加了註解,也增加了讀取註解的api,在java.lang.reflect包中新增了AnnotatedElement介面,JDK原始碼如下:
public interface AnnotatedElement {
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
<T extends Annotation> T getAnnotation(Class<T> annotationClass);
Annotation[] getAnnotations();
Annotation[] getDeclaredAnnotations();
}
isAnnotationPresent:判斷是否標註了指定註解
getAnnotation:獲取指定註解,沒有則返回null
getAnnotations:獲取所有註解,包括繼承自基類的,沒有則返回長度為0的陣列
getDeclaredAnnotations:獲取自身顯式標明的所有註解,沒有則返回長度為0的陣列
通過反射獲取註解屬性值的例子:
public class ProductReflectAnnotation {
@ProductAnnotation(productName="iphone X",publishYear="2017釋出")
private String iphoneX;//iponeX配上註解
@ProductAnnotation(productType= ProductAnnotation.Type.電腦,productName="mac",publishYear="2018釋出")
private String mac;//Mac配上註解
private String noAnnotationField;//noAnnotationField不加註解
public static void main(String[] args) {
// 解析ProductReflectAnnotation類屬性的註解
// getDeclaredFields方法會返回ProductReflectAnnotation類所有的屬性
Field[] fields = ProductReflectAnnotation.class.getDeclaredFields();
for(Field field : fields){
//判斷屬性是否標註了@ProductAnnotation註解
boolean fieldHasAnno = field.isAnnotationPresent(ProductAnnotation.class);
if(fieldHasAnno){
//獲取@ProductAnnotation註解
ProductAnnotation product = field.getAnnotation(ProductAnnotation.class);
//獲取@ProductAnnotation註解 引數值
String name = product.productName();
String publishYear = product.publishYear();
ProductAnnotation.Type type = product.productType();
System.out.println("[" + field.getName() + "] " + name + ","+ type + "," + publishYear);
}
}
}
}
輸出:
[iphoneX] iphone X,手機,2017釋出
[mac] mac,電腦,2018釋出