《重学Java系列》之 注解基础
不詩意的女程序媛不是好廚師~
轉載請注明出處,From李詩雨—[https://blog.csdn.net/cjm2484836553/article/details/104432728]
《重學Java系列之---注解基礎》
- 1.什么是注解?
- 2.自定義注解及使用
- 3.元注解
- 3.1元注解的理解
- 3.2 常見的5種元注解。
- @Retention --- 指定了注解的存活時間
- @Target ---- 指定注解用在什么地方
- @Inherited --- 允許子類繼承父類的注解。
- @Repeatable --- 注解的值可以同時取多個
- @Documented---用到的很少
- 4.注解的屬性
- 5.注解的提取
- 6.注解的使用場景
按照慣例我們先來看下本篇的思維導圖:
本篇來和大家先學習一下注解基礎,后期再一步一步深入學習。
本篇的主要目的就是先對注解有些基本的了解,后期會進行大量的代碼實戰,這樣循序漸進,相信我們就可以很好的掌握注解了。
1.什么是注解?
【注解的定義】:
Java 注解用于為 Java 代碼提供元數據。作為元數據,注解不直接影響你的代碼執行,但也有一些類型的注解實際上可以用于這一目的。Java 注解是從 Java5 開始添加到 Java 的。
【通俗點理解】:
注解即標簽。
如果把代碼想象成一個具有生命的個體,注解就是給這些代碼的某些個體打標簽。
2.自定義注解及使用
- 注解通過 @interface關鍵字進行定義。
它的形式跟接口很類似,不過前面多了一個 @ 符號。
上面的代碼就創建了一個名字為 Test 的注解。你可以簡單理解為創建了一張名字為 Test的標簽。
- 使用注解
創建一個類 TestAnnotation,然后在類定義的地方加上 @Test就可以用 Test注解這個類了。
你可以簡單理解為將 Test 這張標簽貼到 TestAnnotation這個類上面。
3.元注解
3.1元注解的理解
元注解:即注解的注解。
元注解是可以注解到注解上的注解,或者說元注解是一種基本注解,但是它能夠應用到其它的注解上面。
如果難于理解的話,你可以這樣理解。元注解也是一張標簽,但是它是一張特殊的標簽,它的作用和目的就是給其他普通的標簽進行解釋說明的。
3.2 常見的5種元注解。
元注解有 @Retention、@Documented、@Target、@Inherited、@Repeatable 5 種。
下面分別一一來說明:
@Retention — 指定了注解的存活時間
Retention 的英文意為保留期的意思。當 @Retention 應用到一個注解上的時候,它解釋說明了這個注解的的存活時間。
它的取值如下:
我畫一張圖來幫助大家理解 這三個取值下 注解 所能保留到的時期:
@Target ---- 指定注解用在什么地方
Target 是目標的意思,@Target 指定了注解運用的地方
你可以這樣理解,當一個注解被 @Target 注解時,這個注解就被限定了運用的場景。
類比到標簽,原本標簽是你想張貼到哪個地方就到哪個地方,但是因為 @Target 的存在,它張貼的地方就非常具體了,比如只能張貼到方法上、類上、方法參數上等等。@Target 有下面的取值
@Inherited — 允許子類繼承父類的注解。
Inherited 是繼承的意思,但是它并不是說注解本身可以繼承,而是說如果一個超類被 @Inherited 注解過的注解進行注解的話,那么如果它的子類沒有被任何注解應用的話,那么這個子類就繼承了超類的注解。
這么說比較抽象,舉個栗子給大家看看:
現在有一個 美女類Beauty,還有一個它的子類 BeautyChild。
那么當Beauty類被打上了“美女”的標簽后,她的孩子BeautyChild默認也會擁有“美女標簽”。
(PS:也就是美女的孩子還是美女。)
//1.自定義一個使用了@Inherited的標簽 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @Inherited public @interface InheritedTest {String value(); } //2.美女類Beauty,并且擁有一個“美女”標簽 @InheritedTest("美女") public class Beauty { } //3.美女類的孩子類BeautyChild,并沒有特地指定任何標簽 class BeautyChild extends Beauty { } //4.測試:看從子類中能否取到標簽 public class DemoTest {public static void main(String[] args) {Class<BeautyChild> beautyChildClass = BeautyChild.class;if (beautyChildClass.isAnnotationPresent(InheritedTest.class)) {System.out.println(beautyChildClass.getAnnotation(InheritedTest.class).value());}} }結果是:從子類中確實取到了父類所擁有的標簽。
@Repeatable — 注解的值可以同時取多個
Repeatable 是可重復的意思。@Repeatable 是 Java 1.8 才加進來的,所以算是一個新的特性。
什么樣的注解會多次應用呢?通常是注解的值可以同時取多個。
還是來舉個栗子來方便大家理解吧:
比如說我吧,在工作上,我擁有“程序媛”的標簽;在朋友眼中,我擁有“瘋一樣的女子”的標簽;在陌生人眼中,我又擁有“淑女”的標簽。根據不同的場合,我可以擁有很多不同的標簽,這完全沒有問題。
//1.先聲明一個Persons類用來包含所有的身份 @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Persons {Person[] value();//由于會有多個身份,所以此處是數組 } //2.定義一個Person注解,它使用到了@Repeatable。 //@Repeatable括號內的就相當于用來保存該注解內容的容器。 @Repeatable(Persons.class) public @interface Person {String role() default ""; } //3.聲明一個Shiyu類,給該類加上一些身份。 @Person(role = "程序媛") @Person(role = "瘋一樣的女子") @Person(role = "淑女") public class Shiyu { } //4.測試看看能否獲取這多個標簽 public class DemoTest2 {public static void main(String[] args) {if (Shiyu.class.isAnnotationPresent(Persons.class)) {Persons p2 = Shiyu.class.getAnnotation(Persons.class);for (Person t : p2.value()) {System.out.println(t.role());}}} }結果標簽全部可以打印出來,則正確:
【注意事項】:
大家在測試@repeatable的代碼時,別忘了配置gradle哈。要加上下邊這個配置才可以:
即要加上:
compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8 }如果不加的話,編譯時會報錯:
所以,切記這些小細節哈~
@Documented—用到的很少
顧名思義,這個元注解肯定是和文檔有關。它的作用是能夠將注解中的元素包含到 Javadoc 中去。ElementType.TYPE 可以給一個類型進行注解,比如類、接口、枚舉
4.注解的屬性
注解的屬性也叫做成員變量。
注解只有成員變量,沒有方法。
【需要注意】的是:
-
在注解中定義屬性時它的類型是有要求的。
只能用8種基本數據類型( byte,short,char,int,long,float,double,boolean),外加 類(Class),接口(interface),注解(annotation), String,以及這一些類的數組。
-
注解中屬性可以有默認值,默認值需要用 default 關鍵值指定
如:
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Test{int id() default -1;String msg() default "Hello"; }上面代碼定義了 TestAnnotation 這個注解中擁有 id 和 msg 兩個屬性。
在使用的時候,我們應該給它們進行賦值。
賦值的方式是在注解的括號內以 value="" 形式,多個屬性之前用 ,隔開:
@Test(id=1,msg="hello annotation") public class TestAnnotation { }
5.注解的提取
1.運行期注解(RunTime)—利用反射去獲取信息。
2.編譯期(Compile time)注解,以及處理編譯期注解的手段是APT和Javapoet,@Retention(RetentionPolicy.CLASS)。
今天我們主要講一下運行期注解的提取:
首先可以通過 Class 對象的 isAnnotationPresent() 方法判斷它是否應用了某個注解
public boolean isAnnotationPresent(Class<? extends Annotation> annotationClass) {}然后通過 getAnnotation() 方法來獲取 Annotation 對象。
public <A extends Annotation> A getAnnotation(Class<A> annotationClass) {}或者是 getAnnotations() 方法。
public Annotation[] getAnnotations() {}前一種方法返回指定類型的注解,后一種方法返回注解到這個元素上的所有注解。
如果獲取到的 Annotation 如果不為 null,則就可以調用它們的屬性方法了。比如
public class TestDemo {public static void main(String[] args) {boolean hasAnnotation = TestDemo.class.isAnnotationPresent(Test.class);if (hasAnnotation) {TestAnnotation testAnnotation = TestDemo.class.getAnnotation(Test.class);System.out.println("id:" + testAnnotation.id());System.out.println("msg:" + testAnnotation.msg());}} }6.注解的使用場景
- 提供信息給編譯器: 編譯器可以利用注解來探測錯誤和警告信息
- 編譯階段時的處理: 軟件工具可以用來利用注解信息來生成代碼、Html文檔或者做其它相應處理。
- 運行時的處理: 某些注解可以在程序運行的時候接受代碼的提取
值得注意的是,注解不是代碼本身的一部分。
積累點滴,做好自己~
總結
以上是生活随笔為你收集整理的《重学Java系列》之 注解基础的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 携手易维帮助台,神州数码轻松搞定IT外包
- 下一篇: 0基础学习VR全景平台篇第46篇:底部菜