- @Override:用在方法之上,用來告訴別人這一個方法是改寫父類的
- @Deprecated:建議別人不要使用舊的API的時候用的,編譯的時候會用產生警告信息,可以設定在程序裏的所有的元素上.
- @SuppressWarnings:暫時把一些警告信息消息關閉
- @Entity:表示該類是可持久化的類
- package chb.test.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;
- @Target (ElementType.TYPE)
- @Retention (RetentionPolicy.RUNTIME)
- @Documented
- public @interface MyAnnotation1 {
- String value();
- }
- package chb.test.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;
- @Target (ElementType.METHOD)
- @Retention (RetentionPolicy.RUNTIME)
- @Documented
- public @interface MyAnnotation2 {
- String description();
- boolean isAnnotation();
- }
- package chb.test.annotation;
- @MyAnnotation1 ( "this is annotation1" )
- public class AnnotationDemo {
- @MyAnnotation2 (description= "this is annotation2" ,isAnnotation= true )
- public void sayHello(){
- System.out.println("hello world!" );
- }
- }
- package chb.test.annotation;
- import java.lang.reflect.Method;
- import org.junit.Test;
- public class TestAnnotation {
- @Test
- public void test() throws ClassNotFoundException, SecurityException, NoSuchMethodException{
- Class<?> cls = Class.forName("chb.test.annotation.AnnotationDemo" );
- boolean flag = cls.isAnnotationPresent(MyAnnotation1. class );
- if (flag){
- System.out.println("判斷類是annotation" );
- MyAnnotation1 annotation1 = cls.getAnnotation(MyAnnotation1.class );
- System.out.println(annotation1.value());
- }
- Method method = cls.getMethod("sayHello" );
- flag = method.isAnnotationPresent(MyAnnotation2.class ) ;
- if (flag){
- System.out.println("判斷方法也是annotation" );
- MyAnnotation2 annotation2 = method.getAnnotation(MyAnnotation2.class );
- System.out.println(annotation2.description()+"/t" +annotation2.isAnnotation());
- }
- }
- }
this is annotation1
判斷方法也是annotation
this is annotation2 true
- SOURCE:這個Annotation類型的信息只會保留在程序源碼裏,源碼如果經過了編譯之後,Annotation的數據就會消失,並不會保留在編譯好的.class文件裏面
- CLASS:這個Annotation類型的信息保留在程序源碼裏,同時也會保留在編譯好的.class文件裏面,在執行的時候,並不會把這些信息加載到JVM中。注:默認策略爲CLASS類型
- RUNTIME:表示在源碼、編譯好的.class文件中保留信息,在執行的時候會把這一些信息加載到JVM中去的
- 訪問權只能用public和默認(default)修飾
- 參數成員只能用基本類型byte,short,char,int,long,float,double,boolean八種基本數據類型和String,Enum,Class,annotations等數據類型,以及這一些類型的數組
(1) Annotation(註釋)是JDK5.0及以後版本引入的。它可以用於創建文檔,跟蹤代碼中的依賴性,甚至執行基本編譯時檢查。註釋是以‘@註釋名’在代碼中存在的,根據註釋參數的個數,我們可以將註釋分爲:標記註釋、單值註釋、完整註釋三類。它們都不會直接影響到程序的語義,只是作爲註釋(標識)存在,我們可以通過反射機制編程實現對這些元數據的訪問。另外,你可以在編譯時選擇代碼裏的註釋是否只存在於源代碼級,或者它也能在class文件中出現。
元數據的作用
如果要對於元數據的作用進行分類,目前還沒有明確的定義,不過我們可以根據它所起的作用,大致可分爲三類:
編寫文檔:通過代碼裏標識的元數據生成文檔。
代碼分析:通過代碼裏標識的元數據對代碼進行分析。
編譯檢查:通過代碼裏標識的元數據讓編譯器能實現基本的編譯檢查。
基本內置註釋
@Override
- package com.iwtxokhtd.annotation;
- /**
- * 測試Override註解
- * @author Administrator
- *
- */
- public class OverrideDemoTest {
- //@Override
- public String tostring(){
- return "測試註釋";
- }
- }
package com.iwtxokhtd.annotation;
/**
* 測試Override註解
* @author Administrator
*
*/
public class OverrideDemoTest {
//@Override
public String tostring(){
return "測試註釋";
}
}
@Deprecated的作用是對不應該在使用的方法添加註釋,當編程人員使用這些方法時,將會在編譯時顯示提示信息,它與javadoc裏的@deprecated標記有相同的功能,準確的說,它還不如javadoc @deprecated,因爲它不支持參數,使用@Deprecated的示例代碼示例如下:
- package com.iwtxokhtd.annotation;
- /**
- * 測試Deprecated註解
- * @author Administrator
- *
- */
- public class DeprecatedDemoTest {
- public static void main(String[] args) {
- //使用DeprecatedClass裏聲明被過時的方法
- DeprecatedClass.DeprecatedMethod();
- }
- }
- class DeprecatedClass{
- @Deprecated
- public static void DeprecatedMethod() {
- }
- }
package com.iwtxokhtd.annotation;
/**
* 測試Deprecated註解
* @author Administrator
*
*/
public class DeprecatedDemoTest {
public static void main(String[] args) {
//使用DeprecatedClass裏聲明被過時的方法
DeprecatedClass.DeprecatedMethod();
}
}
class DeprecatedClass{
@Deprecated
public static void DeprecatedMethod() {
}
}
@SuppressWarnings,其參數有:
deprecation,使用了過時的類或方法時的警告
unchecked,執行了未檢查的轉換時的警告
fallthrough,當 Switch 程序塊直接通往下一種情況而沒有 Break 時的警告
path,在類路徑、源文件路徑等中有不存在的路徑時的警告
serial,當在可序列化的類上缺少 serialVersionUID 定義時的警告
finally ,任何 finally 子句不能正常完成時的警告
all,關於以上所有情況的警告
- package com.iwtxokhtd.annotation;
- import java.util.ArrayList;
- import java.util.List;
- public class SuppressWarningsDemoTest {
- public static List list=new ArrayList();
- @SuppressWarnings("unchecked")
- public void add(String data){
- list.add(data);
- }
- }
package com.iwtxokhtd.annotation;
import java.util.ArrayList;
import java.util.List;
public class SuppressWarningsDemoTest {
public static List list=new ArrayList();
@SuppressWarnings("unchecked")
public void add(String data){
list.add(data);
}
}
(2)自定義註釋
它類似於新創建一個接口類文件,但爲了區分,我們需要將它聲明爲@interface,如下例:
- public @interface NewAnnotation {
- }
public @interface NewAnnotation {
}
使用自定義的註釋類型
- public class AnnotationTest {
- @NewAnnotation
- public static void main(String[] args) {
- }
- }
public class AnnotationTest {
@NewAnnotation
public static void main(String[] args) {
}
}
爲自定義註釋添加變量
- public @interface NewAnnotation {
- String value();
- }
public @interface NewAnnotation {
String value();
}
- public class AnnotationTest {
- @NewAnnotation("main method")
- public static void main(String[] args) {
- saying();
- }
- @NewAnnotation(value = "say method")
- public static void saying() {
- }
- }
public class AnnotationTest {
@NewAnnotation("main method")
public static void main(String[] args) {
saying();
}
@NewAnnotation(value = "say method")
public static void saying() {
}
}
定義一個枚舉類型,然後將參數設置爲該枚舉類型,並賦予默認值
- public @interface Greeting {
- public enum FontColor{
- BLUE,RED,GREEN
- };
- String name();
- FontColor fontColor() default FontColor.RED;}
- }
public @interface Greeting {
public enum FontColor{
BLUE,RED,GREEN
};
String name();
FontColor fontColor() default FontColor.RED;}
}
這裏有兩種選擇,其實變數也就是在賦予默認值的參數上,我們可以選擇使用該默認值,也可以重新設置一個值來替換默認值
- @NewAnnonation("main method")
- public static void main(String[] args) {
- saying();
- sayHelloWithDefaultFontColor();
- sayHelloWithRedFontColor();
- }
- @NewAnnonation("say method")
- public static void saying(){
- }
- //此時的fontColor爲默認的RED
- @Greeting(name="defaultfontcolor")
- public static void sayHelloWithDefaultFontColor() {
- }
- //現在將fontColor改爲BLUE
- @Greeting(name="notdefault",fontColor=Greeting.FontColor.BLUE)
- public static void sayHelloWithRedFontColor() {
- }
@NewAnnonation("main method")
public static void main(String[] args) {
saying();
sayHelloWithDefaultFontColor();
sayHelloWithRedFontColor();
}
@NewAnnonation("say method")
public static void saying(){
}
//此時的fontColor爲默認的RED
@Greeting(name="defaultfontcolor")
public static void sayHelloWithDefaultFontColor() {
}
//現在將fontColor改爲BLUE
@Greeting(name="notdefault",fontColor=Greeting.FontColor.BLUE)
public static void sayHelloWithRedFontColor() {
}
(3)註釋的高級應用
限制註釋的使用範圍
用@Target指定ElementType屬性
- package java.lang.annotation;
- public enum ElementType {
- TYPE,
- // 用於類,接口,枚舉但不能是註釋
- FIELD,
- // 字段上,包括枚舉值
- METHOD,
- // 方法,不包括構造方法
- PARAMETER,
- // 方法的參數
- CONSTRUCTOR,
- //構造方法
- LOCAL_VARIABLE,
- // 本地變量或catch語句
- ANNOTATION_TYPE,
- // 註釋類型(無數據)
- PACKAGE
- // Java包
- }
package java.lang.annotation;
public enum ElementType {
TYPE,
// 用於類,接口,枚舉但不能是註釋
FIELD,
// 字段上,包括枚舉值
METHOD,
// 方法,不包括構造方法
PARAMETER,
// 方法的參數
CONSTRUCTOR,
//構造方法
LOCAL_VARIABLE,
// 本地變量或catch語句
ANNOTATION_TYPE,
// 註釋類型(無數據)
PACKAGE
// Java包
}
註解保持性策略
- //限制註解使用範圍
- @Target({ElementType.METHOD,ElementType.CONSTRUCTOR})
- public @interface Greeting {
- //使用枚舉類型
- public enum FontColor{
- BLUE,RED,GREEN
- };
- String name();
- FontColor fontColor() default FontColor.RED;
- }
//限制註解使用範圍
@Target({ElementType.METHOD,ElementType.CONSTRUCTOR})
public @interface Greeting {
//使用枚舉類型
public enum FontColor{
BLUE,RED,GREEN
};
String name();
FontColor fontColor() default FontColor.RED;
}
在Java編譯器編譯時,它會識別在源代碼裏添加的註釋是否還會保留,這就是RetentionPolicy。下面是Java定義的RetentionPolicy枚舉:
編譯器的處理有三種策略:
將註釋保留在編譯後的類文件中,並在第一次加載類時讀取它
將註釋保留在編譯後的類文件中,但是在運行時忽略它
按照規定使用註釋,但是並不將它保留到編譯後的類文件中
- package java.lang.annotation;
- public enum RetentionPolicy {
- SOURCE,
- // 此類型會被編譯器丟棄
- CLASS,
- // 此類型註釋會保留在class文件中,但JVM會忽略它
- RUNTIME
- // 此類型註釋會保留在class文件中,JVM會讀取它
- }
package java.lang.annotation;
public enum RetentionPolicy {
SOURCE,
// 此類型會被編譯器丟棄
CLASS,
// 此類型註釋會保留在class文件中,但JVM會忽略它
RUNTIME
// 此類型註釋會保留在class文件中,JVM會讀取它
}
- //讓保持性策略爲運行時態,即將註解編碼到class文件中,讓虛擬機讀取
- @Retention(RetentionPolicy.RUNTIME)
- public @interface Greeting {
- //使用枚舉類型
- public enum FontColor{
- BLUE,RED,GREEN
- };
- String name();
- FontColor fontColor() default FontColor.RED;
- }
//讓保持性策略爲運行時態,即將註解編碼到class文件中,讓虛擬機讀取
@Retention(RetentionPolicy.RUNTIME)
public @interface Greeting {
//使用枚舉類型
public enum FontColor{
BLUE,RED,GREEN
};
String name();
FontColor fontColor() default FontColor.RED;
}
文檔化功能
Java提供的Documented元註釋跟Javadoc的作用是差不多的,其實它存在的好處是開發人員可以定製Javadoc不支持的文檔屬性,並在開發中應用。它的使用跟前兩個也是一樣的,簡單代碼示例如下:
- //讓它定製文檔化功能
- //使用此註解時必須設置RetentionPolicy爲RUNTIME
- @Documented
- public @interface Greeting {
- //使用枚舉類型
- public enum FontColor{
- BLUE,RED,GREEN
- };
- String name();
- FontColor fontColor() default FontColor.RED;
- }
//讓它定製文檔化功能
//使用此註解時必須設置RetentionPolicy爲RUNTIME
@Documented
public @interface Greeting {
//使用枚舉類型
public enum FontColor{
BLUE,RED,GREEN
};
String name();
FontColor fontColor() default FontColor.RED;
}
標註繼承
- //讓它允許繼承,可作用到子類
- @Inherited
- public @interface Greeting {
- //使用枚舉類型
- public enum FontColor{
- BLUE,RED,GREEN
- };
- String name();
- FontColor fontColor() default FontColor.RED;
- }
//讓它允許繼承,可作用到子類
@Inherited
public @interface Greeting {
//使用枚舉類型
public enum FontColor{
BLUE,RED,GREEN
};
String name();
FontColor fontColor() default FontColor.RED;
}
(4)讀取註解信息
屬於重點,在系統中用到註解權限時非常有用,可以精確控制權限的粒度
- package com.iwtxokhtd.annotation;
- import java.lang.annotation.Annotation;
- import java.lang.reflect.Method;
- //讀取註解信息
- public class ReadAnnotationInfoTest {
- public static void main(String[] args)throws Exception {
- //測試AnnotationTest類,得到此類的類對象
- Class c=Class.forName("com.iwtxokhtd.annotation.AnnotationTest");
- //獲取該類所有聲明的方法
- Method []methods=c.getDeclaredMethods();
- //聲明註解集合
- Annotation[] annotations;
- //遍歷所有的方法得到各方法上面的註解信息
- for(Method method:methods){
- //獲取每個方法上面所聲明的所有註解信息
- annotations=method.getDeclaredAnnotations();
- //再遍歷所有的註解,打印其基本信息
- for(Annotation an:annotations){
- System.out.println("方法名爲:"+method.getName()+" 其上面的註解爲:"+an.annotationType().getSimpleName());
- Method []meths=an.annotationType().getDeclaredMethods();
- //遍歷每個註解的所有變量
- for(Method meth:meths){
- System.out.println("註解的變量名爲:"+meth.getName());
- }
- }
- }
- }
- }
package com.iwtxokhtd.annotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
//讀取註解信息
public class ReadAnnotationInfoTest {
public static void main(String[] args)throws Exception {
//測試AnnotationTest類,得到此類的類對象
Class c=Class.forName("com.iwtxokhtd.annotation.AnnotationTest");
//獲取該類所有聲明的方法
Method []methods=c.getDeclaredMethods();
//聲明註解集合
Annotation[] annotations;
//遍歷所有的方法得到各方法上面的註解信息
for(Method method:methods){
//獲取每個方法上面所聲明的所有註解信息
annotations=method.getDeclaredAnnotations();
//再遍歷所有的註解,打印其基本信息
for(Annotation an:annotations){
System.out.println("方法名爲:"+method.getName()+" 其上面的註解爲:"+an.annotationType().getSimpleName());
Method []meths=an.annotationType().getDeclaredMethods();
//遍歷每個註解的所有變量
for(Method meth:meths){
System.out.println("註解的變量名爲:"+meth.getName());
}
}
}
}
}
轉自:http://iwtxokhtd.javaeye.com/blog/359939