一、 什麼是註解 html
Annotation表示一種註釋的語法,在 Java 中最先提倡的是程序與配置相分離,而最新的理論是把全部配置直接寫入到代碼中,若是想完成這樣的功能,則使用 Annotation 。 java
二、 系統內建的Annotation api
2.1 @Override 數組
重寫父類的方法 eclipse
2.2 @Deprecated 編輯器
表示不建議使用的操做,若是使用該操做也不報錯,只是在編輯器中出現橫線警告信息,不建議使用。如Date 對像中的不少方法。 ide
@ Deprecated 工具
public int getDay () { url
return normalize () .getDayOfWeek () - gcal.SUNDAY; spa
}
2.3 @SuppressWaring表示壓制警告,若是出現警告信息,則能夠壓制不提示。 @SuppressWaring 的屬性String[] value() 爲數組,說明能夠同時壓制多個警告。
@ Target ({ TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE })
@ Retention ( RetentionPolicy.SOURCE )
public @interface SuppressWarnings {
String [] value () ;
}
三、自定義 Annotation
3.1 語法
public @interface 名稱 {
}
3.2 定義 MyAnnotaion
package com.chenzehe.annotation;
public @interface MyAnnotation {
}
若是要使用此Annotation, 則使用 @ 符訪問,不在同一個包中須要導入。以下面 Info 類的使用:
package com.chenzehe.annotation;
@MyAnnotation
public class Info {
}
3.3 Annotation的屬性定義
Annotation的屬性定義以 () 結尾。
package com.chenzehe.annotation;
public @interface MyAnnotation {
public String key () ;
public String value () ;
}
上面Annotation 定義了兩個變量 key 和 value ,若是要使用此 Annotation ,則必須明確的給出其內容。如:
package com.chenzehe.annotation;
@MyAnnotation ( key= "name" ,value= "chenzehe" )
public class Info {
}
若是想給Annotation 的變量設置默認值,則使用 default 關鍵字完成,如:
package com.chenzehe.annotation;
public @interface MyAnnotation {
public String key () default "name" ;
public String value () default "chenzehe" ;
}
使用此Annotation 時,能夠不用顯示的設置變量值,而使用默認值。
3.4 Annotation中的屬性值能夠經過枚舉限制
定義枚舉類型Color:
package com.chenzehe.annotation;
public enum Color {
RED , GLREN , BLUE ;
}
在MyAnnotation 中定義一個 Color 類型的變量:
package com.chenzehe.annotation;
public @interface MyAnnotation {
public Color color () default Color. RED ;
}
則使用MyAnnotation 中的 color 變量時,值只能取 Color 中定義的類型:
package com.chenzehe.annotation;
@MyAnnotation ( color= "red" )
public class Info {
}
上面給變量color 賦值出錯,正確以下:
package com.chenzehe.annotation;
@MyAnnotation ( color = Color. RED )
public class Info {
}
3.5 Annotation中的屬性爲數組類型
若是Annotation 中的屬性爲數組類型,則使用的時候必須按照數組的方式操做。
package com.chenzehe.annotation;
public @interface MyAnnotation {
public String [] urls () ;
}
使用:
package com.chenzehe.annotation;
@MyAnnotation ( urls = { "www.baidu.com" , "g.cn" })
public class Info {
}
四、 註釋類型 Retention 和 枚舉 RetentionPolicy
@Retention ( value = RUNTIME )
@Target ( value = ANNOTATION_TYPE )
public @interface Retention
指示注 解 類型的註釋要保留多久 ,也就是做用範圍。 若是註釋類型聲明中不存在 Retention 註釋,則保留策略默認爲 RetentionPolicy.CLASS 。只有元註釋類型直接用於註釋時, Target 元註釋纔有效。若是元註釋類型用做另外一種註釋類型的成員,則無效。
枚舉 RetentionPolicy 定義了三種 Annotation的範圍:
CLASS 在編譯以後的 class文件中做用
RUNTIME 在運行的時候起做用
SOURCE 只在源代碼中起做用
系統內置的三個Annotation 的做用域分別爲:
@ Override : @Retention ( value = SOURCE ) 源碼
@ Deprecated : @Retention ( value = RUNTIME ) 運行時
@ SuppressWarnings : @Retention ( value = SOURCE ) 源碼
五、 反射與Annotation
一個Annotation 若是要想起做用,則確定要依賴反射機制,經過反射能夠取得一個方法上聲明的 Annotation所有內容。任何一下自定義的 Annotation 都是繼承了 java.lang.annotation.Annotation 接口。
在 Field Method Constructor 的父類 AccessibleObject 定義了以下與Annotation 操做相關的方法:
取得所有Annotation : public Annotation [] getAnnotations ()
判斷操做的是不是指定的Annotation : public boolean isAnnotationPresent ( Class <? extends Annotation> annotationClass)
例:下面Info 類中 toString() 方法使用的 Annotation ,在 Test 類中用反射訪問這些 Annotation
package com.chenzehe.annotation;
public class Info {
@Override
@Deprecated
@SuppressWarnings ( value = "" )
public String toString () {
return "Hello World!" ;
}
}
package com.chenzehe.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class Test {
public static void main ( String [] args ) throws Exception {
Class<?> cls = Class. forName ( "com.chenzehe.annotation.Info" ) ;
Method method = cls.getMethod ( "toString" ) ;
Annotation [] annotations = method.getAnnotations () ;
for ( int i = 0; i < annotations. length ; i ++ ) {
System. out .println ( annotations [ i ]) ;
}
}
}
輸出:@java.lang.Deprecated() ,而 Info 類中使用的三個 Annotation 中,只有 Deprecated 的範圍爲 runtime ,說明只有範圍在 runtime 的才能被找到。
把MyAnnotation 類改爲 runtime 範圍,並在 Test 類中用反射取得他的屬性:
package com.chenzehe.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention ( value = RetentionPolicy. RUNTIME )
public @interface MyAnnotation {
public String key () default "name" ;
public String value () ;
}
在 Info中使用該 Annotation :
package com.chenzehe.annotation;
public class Info {
@Override
@Deprecated
@SuppressWarnings ( value = "" )
@MyAnnotation ( value= "chenzehe" )
public String toString () {
return "Hello World!" ;
}
}
在 Test類中使用反射取得其屬性:
package com.chenzehe.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
public class Test {
public static void main ( String [] args ) throws Exception {
Class<?> cls = Class. forName ( "com.chenzehe.annotation.Info" ) ;
Method method = cls.getMethod ( "toString" ) ;
Annotation [] annotations = method.getAnnotations () ;
for ( int i = 0; i < annotations. length ; i++ ) {
if ( method.isAnnotationPresent ( MyAnnotation . class )) {
MyAnnotation myAnnotation = method.getAnnotation ( MyAnnotation . class ) ;
String key = myAnnotation.key () ;
String value = myAnnotation.value () ;
System. out .println ( key + ":" + value ) ;
}
}
}
}
六、 Target
在java.lang.annotation 中已定義的註解類型 Target ,用於指定所定義的註解使用的範圍爲方法、類、屬性等。
默認狀況下一個自定義的Annotation 能夠在任意地方使用,如自定義的 MyAnnotation ,若是沒有指定 Target ,則能夠在任意地方使用:
package com.chenzehe.annotation;
@MyAnnotation ()
public class Info {
@MyAnnotation ()
private String name ;
@MyAnnotation ()
public String toString () {
return "Hello World!" ;
}
}
在Target 的定義中, value 的屬性類型爲 ElementType [] ,所指定的範圍有如下八種:
一、 只能在Annotation 中出現: ANNOTATION_TYPE
二、 只能在構造方法中出現: CONSTRUCTOR
三、 在屬性中出現: FIELD
四、 只能在本地變量中出現: LOCAL_VARIABLE
五、 在方法上出現: METHOD
六、 在包聲明中出現: PACKAGE
七、 在參數聲明中出現: PARAMETER
八、 類、接口(包括註釋類型)或枚舉聲明 中使用: TYPE
如如下自定義的MyAnnotation 只能在方法中使用:
package com.chenzehe.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention ( value = RetentionPolicy. RUNTIME )
@Target ( value= ( ElementType. METHOD ))
public @interface MyAnnotation {
public String key () default "name" ;
public String value () default "chenzehe" ;
}
Target中的屬性 value 定義爲數組類型,因此能夠同時設置多個 ElementType ,如:
@Target ( value = { ElementType. METHOD , ElementType. FIELD })
七、 Document註解
在java.lang.annotation 中定義的註解類型 Documented , 指示某一類型的註釋將經過 javadoc 和相似的默認工具進行文檔化。應使用此類型來註釋這些類型的聲明:其註釋會影響由其客戶端註釋的元素的使用。若是類型聲明是用 Documented 來註釋的,則其註釋將成爲註釋元素的公共 API 的一部分。
如聲明 MyAnnotation註解:
package com.chenzehe.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Documented
@Retention ( value = RetentionPolicy. RUNTIME )
@Target ( value = { ElementType. METHOD , ElementType. FIELD })
public @interface MyAnnotation {
public String key () default "name" ;
public String value () default "chenzehe" ;
}
在Info 類中使用:
package com.chenzehe.annotation;
public class Info {
/**
* 此方法是覆蓋Object中的toString()方法
*/
@ MyAnnotation ()
public String toString () {
return "Hello World!" ;
}
}
能夠經過eclipse 的 export 導出 javadoc ,在其註釋中能看到上面編寫的註釋
八、 Inherited
在java.lang.annotation 中聲明 Inherited ,表示該annotation 是否被該子類斷承下去,若是沒有此註解,說明不能被斷承。
如自定義的MyAnnotation ,加入 @Inherited ,說明此 Annotation 能夠被子類斷承:
package com.chenzehe.annotation;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Inherited
@Retention ( value = RetentionPolicy. RUNTIME )
public @interface MyAnnotation {
public String key () default "name" ;
public String value () default "chenzehe" ;
}
在 Info類中使用該 Annotation :
package com.chenzehe.annotation;
@ MyAnnotation
public class Info {
}
建立Info 類的子類 PersonInfo :
package com.chenzehe.annotation;
public class PersonInfo extends Info {
}
使用反射取得PersonInfo 類的 annotation 信息:
package com.chenzehe.annotation;
import java.lang.annotation.Annotation;
public class Test {
public static void main ( String [] args ) throws Exception {
Class<?> cls = Class. forName ( "com.chenzehe.annotation.PersonInfo" ) ;
Annotation [] annotations = cls.getAnnotations () ;
for ( int i = 0; i < annotations. length ; i++ ) {
System. out .println ( annotations [ i ]) ;
}
}
}
若是MyAnnotation 中加入 @Inherited ,則能夠取到 MyAnnotaion信息,若是沒有加則取不到。