註解是jdk1.5新增的特性.大家都知道,jdk1.5在java的發展史上有著劃時代的意義.而註解的出現,在某種程度上顛覆了框架的設計.比如,spring在註解出現後,改善了原先五大組件的模式,增加了基於註解的實現方式.現在重點講講註解的使用. 元註解: jdk1.5定義了4個元註解,元註解的作用是 ...
註解是jdk1.5新增的特性.大家都知道,jdk1.5在java的發展史上有著劃時代的意義.而註解的出現,在某種程度上顛覆了框架的設計.比如,spring在註解出現後,改善了原先五大組件的模式,增加了基於註解的實現方式.現在重點講講註解的使用.
元註解:
jdk1.5定義了4個元註解,元註解的作用是註解其他的註解.
1.@Retention
2.@Target
3.@Documented
4.@Inherited
@Retention用於指明該註解存在的時機.參數有三個值可選:RetentionPolicy.SOURCE,RetentionPolicy.CLASS,RetentionPolicy.RUNTIME可供選擇.分別表示:源碼中保留註解,位元組碼文件中保留註解,運行時保留註解.
@Target用於指明註解能作用的範圍.比如參數中設置為ElementType.TYPE,表示作用於類和介面.如果你用來註解方法,則會發生編譯錯誤.由此可見它的功能是通過編譯器實現的.
@Documented表明該註解在使用javadoc工具生成開發文檔時,也會被納入進去.
@Inherited表明,某個位置使用該註解,那麼在存在Java繼承關係的地方,該註解也能被繼承過來.這個可能不好理解.下麵的代碼加以說明.
1 @Retention(RetentionPolicy.RUNTIME) 2 @Target({ElementType.TYPE,ElementType.METHOD}) 3 @Inherited 4 public @interface AnnoInherited { 5 6 }
測試代碼:
1 public class TestAnnoInherated { 2 public static void main(String[] args) { 3 Annotation[] annos=new Goo().getClass().getAnnotations(); 4 for(Annotation a:annos){ 5 System.out.println(a); 6 } 7 } 8 } 9 10 @AnnoInherited 11 class Foo{ 12 13 } 14 15 class Goo extends Foo{ 16 17 }
控制台輸出:
@test.annotation.AnnoInherited()
上例中Goo前面並沒有加註解@AnnoInherited,但是父類Foo前面有,而@AnnoInherited加了元註解@Inherited,所以Foo能繼承過來.
自定義註解:
自定義註解的實例如下.
package 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 AnimalInfo { String shout() default ""; //能不能看門 boolean isGuard() default true; }
測試代碼:
public class TestAnimalInfo { public static void main(String[] args) { Animal animal=new Animal(); AnimalInfo info=animal.getClass().getAnnotation(AnimalInfo.class); if(info!=null){ Annotation anno=info;//此處並沒有報錯.Annotation是一個介面.info是一個註解.這是因為編譯器會將註解編譯成介面,並且繼承了Annotation System.out.println("Annotation類信息:"+Annotation.class); System.out.println("AnimalInfo類信息:"+AnimalInfo.class); Class[] cs=AnimalInfo.class.getInterfaces(); for(Class c:cs){ System.out.println(c); //AnimalInfo編譯後就是一個介面,並且繼承了Annotation,這裡得到了證實. } System.out.println("info對象的類信息:"+info.getClass()); if("wangwang".equals(info.shout())&&info.isGuard()){ System.out.println("the animal is a dog"); }else if("miaomiao".equals(info.shout())&&!info.isGuard()){ System.out.println("the animal is a cat"); }else{ System.out.println("the animal is not a dog or cat"); } }else{ System.out.println("it's not a animal"); } } } @AnimalInfo(shout="wangwang",isGuard=true) class Animal{ }
控制台輸出:
Annotation類信息:interface java.lang.annotation.Annotation AnimalInfo類信息:interface test.annotation.AnimalInfo interface java.lang.annotation.Annotation info對象的類信息:class com.sun.proxy.$Proxy1 the animal is a dog
代碼分析:從控制台可以看到.@AnimalInfo註解其實編譯後就是介面,並且它繼承了Annnotation.而通過反射獲得的註解實例,名字為$Proxy1,是一個類的對象.可見,該註解實例是JVM通過動態代理技術生成的.這也揭示了註解特性的底層實現原理.關於註解的具體底層技術原理,這裡不再詳談.