#1.什麼是註解?
註解也叫元數據(用來描述數據的數據),它用來對某些元素進行說明/註釋等。
註解是一個接口,程序能夠經過反射來獲取指定元素的Annotaion,而後經過Annotation對象來獲取註解裏面的元數據。
#2.註解的所用?
2.1 建立文檔,經過在代碼裏標識註解生成[doc文檔]。
2.2 跟蹤代碼的依賴性,配置依賴信息可使用xml文檔與註解兩種形式 。
2.3 執行編譯時檢查,如@override放在方法前,若是這個方法不是重寫父類的方法,則編譯報錯。
#3.註解的分類
3.1 標記註解,Annotation類型沒有成員變量,例如Override。
3.2 單值註解。
3.3 完整註解。
#4.註解的分類
4.1 jdk自帶註解
@Override:重寫父類中方法。
@Deprecated:代表該類、方法不建議使用。
@SuppressWarnings:忽略警告。
4.2 元註解
4.3 自定義註解
#5.java提供的註解
@Target、@Retention、@Documented、@Inherited
5.1 @Target
@Target說明了Annotation修飾對象的範圍,Annotaion能夠用於packages、types(類、接口、枚舉、Annotation類型)、types成員(方法、構造方法、成員變量、枚舉值)。
做用:描述該註解使用的範圍
取值(ElementType)有:
1.TYPE:類、接口(包括註解)、枚舉聲明
2.FIELD:域變量(包括枚舉常量)
3.METHOD:方法
4.PARAMETER:描述參數
5.CONSTRUCTOR:構造器
6.LOCAL_VARIABLE:局部變量
7.ANNOTATION_TYPE:註解類型
8.PACKAGE:包
舉例java
@Target(ElementType.METHOD) public @interface Override { }
說明:Override這個註解只能用於方法上面。
5.2 @Retention
@Retention定義了該註釋保留多長時間,默認是RetentionPolicy.CLASS,即在class文件中有效。
做用:描述該註解的生命週期
取值(RetentionPolicy)有:
1.SOURCE:在源文件中有效,編譯時被丟棄
2.CLASS:在類文件中有效,編譯時被記錄,在運行時被丟棄
3.RUNTIME:在運行時有效
舉例api
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Column { public String name() default "fieldName"; }
說明:Column註解可用於變量上面,在運行時有效。Column註解的屬性值是運行時,所以這樣的註解能夠經過反射獲取到該註解的屬性值。
5.3 @Documented
做用:生成javadoc文檔,@Documented註解是一個標記註解,沒有成員。
5.4 @Inherited
@Inherited是一個標記註解,@Inherited表示它修飾的對象類型是能夠被繼承的。
#6.自定義註解
使用@interface自定義註解時,自動繼承了java.lang.annotation.Annotation接口。在自定義註解時,不能繼承其它的註解或接口。@interface用來申明一個註解,其中每個方法其實是聲明瞭一個配置參數。方法的名稱就是參數參數的名稱,返回值類型就是參數類型。
以下是自定義註解
1.水果名稱註解ide
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitType { String value() default ""; }
2.水果顏色註解工具
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitColor { enum Color{BULE,RED,GREEN;} Color fruitColor() default Color.BULE; }
3.水果提供商註解ui
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitProvider { //供應商編號 public int id() default 1; //供應商名稱 public String name() default ""; //供應商地址 public String address() default ""; }
#7.註解處理器
定義了註解,若是不使用,那也沒用。
使用註解,必須建立註解處理器,java中利用反射機制,能夠幫咱們構造註解處理器。
java使用Annotation接口來表示程序元素前面的註解,java在reflect包下新增了AnnotatedElement接口,該接口能夠接受註解的程序元素,該接口主要的實現類
Class、Constructor、Field(類的成員變量)、Method、Package
java.lang.reflect包下主要是一些實現反射功能的工具類,該包提供了反射api來讀取運行時Annotation信息。
AnnotatedElement接口是全部程序元素(Class、Constructor、Field(類的成員變量)、Method、Package)的父接口,因此程序經過反射獲取了整個類的AnnotatedElement對象以後,程序就能夠調用該對象以下四個方法來訪問Annotation信息:
getAnnotation(Class<T> annotationClass):返回程序元素上指定類型的註解,若是註解不存在,則返回null
getAnnotations:返回程序元素上全部的註解
getDeclaredAnnotations:返回程序元素上全部的註解,忽略父級註解
isAnnotationPresent(Class<? extends Annotation> annotationClass):判斷程序元素上是否包含指定類型的註解(@Target、@Retention、@Documented、@Inherited ),存在則返回true,不然返回false。 註解處理器以下.net
/** * 註解處理器 */ public class FruitUtil { public static void getFruitUtil(Class<?> clazz) { //定義變量 String strFruitName = "水果名稱:"; String strFruitColor = "水果顏色:"; String strFruitProvider = "供應商信息:"; //getDeclaredFields:獲取clazz類裏面全部的屬性 Field[] fields = clazz.getDeclaredFields(); //循環註解 for(Field field:fields) { //若是FruitType上包含註解 if (field.isAnnotationPresent(FruitType.class)) { //獲取該程序元素 FruitType fruitName = (FruitType)field.getAnnotation(FruitType.class); //獲取該程序元素的註解值 strFruitName = strFruitName+fruitName.value(); //打印註解值 //備註:實際工程中,這裏根據拿到的註解值作相關的業務 System.out.println(strFruitName); }else if (field.isAnnotationPresent(FruitColor.class)) { FruitColor fruitColor = (FruitColor)field.getAnnotation(FruitColor.class); strFruitColor = strFruitColor+fruitColor.fruitColor(); System.out.println(strFruitColor); }else if (field.isAnnotationPresent(FruitProvider.class)) { FruitProvider fruitProvider = (FruitProvider)field.getAnnotation(FruitProvider.class); strFruitProvider = strFruitProvider+"供應商編號:"+ fruitProvider.id()+";"+ "供應商名稱"+ fruitProvider.name()+";"+ "供應商地址"+ fruitProvider.address(); System.out.println(strFruitProvider); } } } }
採用如上方法拿到了註解值,而後能夠作相關的處理操做。可是相關的操做,不能影響主業務。code