Java-了解注解及其應用
一、注解基本了解和應用
1、何為注解?
注解就是一種標記,在程序中加了注解就等于加了標記,沒加,就沒有標記。
2、注解有何作用?
加了注解,java編譯器、開發工具或是其他程序可以通過反射技術了解你的類或各種元素是否有標記,有什么標記就做什么
樣的事情。比如:子類重寫父類的方法,方法上必須有@override標記;若一個方法已過時不用了,就該方法添加注
解@Deprecated,調用者反射時就明白這方法已過時
3、注解在哪標記,也就是說能為哪些元素標記?
可以在包、類、字段、方法、局部變量
二、自定義注解及其應用
1、先定義個注解類,如下代碼:
/** * 自定義注解類 * @author Administrator * */ public @interface AnimTest { } |
2、將這個注解類應用到某個類上,然后用反射查看判斷該類是否被這個注解類所標記
package com.itcast.test; import com.itcast.zhujie.AnimTest; @AnimTest //這是自定義的注解 public class ZhujieTest { /** * @param args */ public static void main(String[] args) { boolean isAnim = ZhujieTest.class.isAnnotationPresent(AnimTest.class); if(isAnim) System.out.println("it has one"); else System.out.println("no have"); } } |
輸出的結果是:no have ;表示該類沒有找到注解標記,這是為何呢?不是在類上已經使用了注解了嘛?
回答這問題之前,我們先學習一個東西,Retention元注釋類,指的是注釋類型的注釋要留多久。如果某個注釋類型沒有聲明Retention元注釋,則保留策略為默認的RetentionPolicy.CLASS,表示保留到編譯時,運行時就會被剔除。 RetentionPolicy 是一個枚舉類型,有三個值:SOURCE、CLASS 、 RUNTIME 分別對應著Java源文件、class文件、內存中的字節碼
我們在重新看下上個代碼,AnimTest 沒有聲明Retention,故保留默認的CLASS,只保留到編譯時期。所以內存中加載類文件時,注解類已被清除,所以才會找不到AnimTest注解類的標記。要想在反射中能找到該標記,只要設置下注解類的保留周期,所以接著改下這個注解類
/** * 自定義注解類 * @author Administrator * */ @Retention(value = RetentionPolicy.RUNTIME) //表示運行時也保留該注解類 public @interface AnimTest { } |
在執行代碼,結果是:it has one
3、現在有個問題,就是注解類的使用范圍是怎樣的呢?只能在類上么?
其實有個元注釋Tagert來限定范圍的。Tagert 指的是注釋類型所適用的程序元素的種類。如果注釋類沒有聲明Tagert元注釋,則可以適用于任何元素上,如果聲明了,編譯器就會強制實施指定的范圍
如果要使AnimTest只作用于方法上,則在注釋類聲明Tagert
/** * 自定義注解類 * @author Administrator * */ @Retention(value = RetentionPolicy.RUNTIME) @Target(value = {ElementType.METHOD}) //限定范圍,作用于方法 public @interface AnimTest { } |
那么這個注解類就不能作用于類上了,否則會編譯異常,只能作用于方法上,代碼如下:
public class ZhujieTest { /** * @param args */ @AnimTest //作用于方法上 public static void main(String[] args) { boolean isAnim = ZhujieTest.class.isAnnotationPresent(AnimTest.class); if(isAnim) System.out.println("it has one"); else System.out.println("no have"); } } |
如果注釋類既可以使用類上也可以作用 于方法上,只要修改為 @Target(value = {ElementType.METHOD,ElementType.TYPE}),type是表示類型
三、為注解增加各種屬性
1、現在給注解類添加各種屬性,類似接口形式,只提供方法
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import com.itcast.classdemo.WeekDay; /** * 自定義注解類 * @author Administrator * */ @Retention(value = RetentionPolicy.RUNTIME) @Target(value = {ElementType.METHOD,ElementType.TYPE,ElementType.ANNOTATION_TYPE}) public @interface AnimTest { String color(); //字符串 int count(); //整型 int[] arr(); //數組 MetaAnnotation meta() default @MetaAnnotation("very food"); //注釋類型 WeekDay day() default WeekDay.MON; //枚舉類型 } //注釋類 public @interface MetaAnnotation { String value() default "heollo"; //提供默認值 } //枚舉類 public enum WeekDay { SUN,MON } |
2、以下是測試注釋類調用屬性
import com.itcast.zhujie.AnimTest; @AnimTest (color ="red",count =1,arr=234) //這是自定義的注解,并為其屬性賦值 public class ZhujieTest { /** * @param args */ @AnimTest (color ="blue",count=2,arr={3,21}) public static void main(String[] args) { //是否含有AnimTest注釋標記 boolean isAnim = ZhujieTest.class.isAnnotationPresent(AnimTest.class); if(isAnim){ //獲取AnimTest注釋標記對象 AnimTest an = ZhujieTest.class.getAnnotation(AnimTest.class); //以下都是獲取AnimTest注釋標記對象的屬性 System.out.println(an.color()); // red System.out.println(an.count()); //1 System.out.println(Arrays.toString(an.arr())); //[234] System.out.println(an.meta().value()); //very good System.out.println(an.day()); //MON System.out.println("it has one"); }else System.out.println("no have"); } } |
經上述測試總結:
1)注釋類的屬性可以有String、int、數組、枚舉和注解
2)注釋類的屬性可以設置默認值,如String color() default "red";
3)在使用注釋類時,有屬性,但沒默認值,這時必須要賦值,否則編譯不通 過 @AnimTest (color ="blue",count=2,arr={3,21})
4)獲取類上的注釋對象,用反射技術AnimTest an = ZhujieTest.class.getAnnotation(AnimTest.class);
5)獲取注釋上的屬性,類似調用方法一樣,需要帶括號;
6)如果注釋類只有一個屬性要賦值,且屬性名為value,則賦值時屬性名和等號都可以省略,如:@MetaAnnotation("very food")
posted on 2014-03-28 11:17 順其自然EVO 閱讀(396) 評論(0) 編輯 收藏 所屬分類: 測試學習專欄