1、Annotation(註解) 概述
(1)、註解起到標識做用,比如Junit的@Test註解。
Junit會在運行時檢查方法上是否存在此註解,如果存在,就通過 反射 來運行你的方法。注意標紅的反射兩個字,反射在註解裏相當重要,寫完你的自定義註解類後沒啥用,必須要用反射才能讓它動起來!所以需要對反射有了解,感興趣的小可愛可以看下這篇:Java中的反射機制介紹
(2)、從 JDK 5.0 開始,Java 增加了對 Annotation(註解)的支持。
(3)、 註解其實就是代碼裏的特殊標記,它可以用於替代配置文件,也就是說,傳統方式通過配置文件告訴類如何運行,有了註解技術後,開發人員可以通過註解告訴類如何運行。用了註解以後,可以減少項目的配置文件,使代碼看起來更優雅。在Java技術裏註解的典型應用是:可以通過反射技術去得到類裏面的註解,以決定怎麼去運行類。
(4)、註解可以代替配置文件會被大量的應用到實際項目中去,又由於註解看起很簡潔,因此如果對註解的知識瞭解的不夠的話,到項目應用中,有時候你會一頭霧水,不知道咋回事,會比較懵。所以,學好註解非常重要
(5)、掌握註解技術的要點: 如何定義註解、如何反射註解,並根據反射的註解信息,決定如何去運行類
2、自定義 Annotation
2.1、定義註解本身
使用關鍵字@interface定義一個類而已。這個類就是註解。
如:public @interface MyAnnotation{ }
2.2、定義註解中的屬性
基本形式:類型 屬性名稱();
比如:String name();
註解屬性定義完以後,使用:@MyAnnotationDemo1(name="hello")
特別注意:註解的屬性的類型只能是:基本類型、String、Class、枚舉、註解類型及以上類型的一維數組。
2.3、定義註解屬性的默認值
類型 屬性名稱() default 默認值;
2.4、註解中的特殊屬性
(1)、特殊屬性value:如果註解中只有一個屬性,而且這個屬性的名稱是value的話,那麼使用註解時可以省略value=部分,可以直接寫成這樣@MyAnnotation(“xxx");
(2)、特殊類型[] value():如果註解中只有一個屬性,而且這個屬性名稱是value且數據類型是數組,那麼
使用方式:四種都ok,根據情況而定
@MyAnnotationDemo1(value={"a","b"})
@MyAnnotationDemo1({"a","b"})
@MyAnnotationDemo1({"a"})
@MyAnnotationDemo1("a")
以上就是註解的基本語法了,下面通過代碼寫一個真實的小案例,來感受一下註解
3、寫一個自定義註解的真實案例
按照上邊介紹的語法,開始自定義一個註解來模擬實現 @Test單元測試的功能
package com.cj.study.annotation.app1;
public @interface MyTest {
}
package com.cj.study.annotation.app1;
public class DemoTest1 {
@MyTest
public void test1(){
System.out.println("test1執行了");
}
public void test2(){
System.out.println("test2執行了");
}
}
package com.cj.study.annotation.app1;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//反射註解:
//取得類的字節碼
//反射其中的成員,此處就是方法成員
//看誰的上面有MyTest註解
//誰有,就執行誰
public class MyJunitRunner {
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
//取得類的字節碼
Class clazz = DemoTest1.class;
//反射其中的成員,此處就是方法成員
Method methods[] = clazz.getMethods();//得到DemoTest1中的所有公有的方法
//看誰的上面有MyTest註解
for(Method m:methods){
//誰有,就執行誰
boolean b = m.isAnnotationPresent(MyTest.class);
System.out.println(b+"==="+m.getName());
if(b){
m.invoke(clazz.newInstance(), null);
}
}
}
}
如果運行結果出現test1方法執行了,test2方法沒執行的話,就對了。
運行看下運行結果:
但是從結果可以看出和咱們預期的並不一樣,那到底怎麼回事呢?
原因是:定義註解的時候除了上邊說的語法,還需要一個東西,那就是“元註解”
那什麼是元註解呢?
簡單的來說服務於註解的註解就是元註解,它主要用來標識你寫的註解保留範圍(作用範圍)以及出現的位置
JDK中定義了四種元註解:
@Retention:註解的保留範圍,是個枚舉,有如下可選值
RetentionPolicy.SOURCE:註解存在於源文件中
RetentionPolicy.CLASS:註解存在於源字節碼文件中
RetentionPolicy.RUNTIME:註解存在於運行時
@Target:註解出現的位置(比如字段上、方法上等),也是個枚舉,有如下可選值
ElementType.TYPE
ElementType.FIELD:字段
ElementType.METHOD:方法
ElementType.PARAMETER
ElementType.CONSTRUCTOR
ElementType.LOCAL_VARIABLE
ElementType.ANNOTATION_TYPE
ElementType.PACKAGE
ElementType.TYPE_PARAMETER
ElementType.TYPE_USE
@Documented: 用於指定被該元 Annotation 修飾的 Annotation 類將被 javadoc 工具提取成文檔.
@Inherited: 被它修飾的 Annotation 將具有繼承性.如果某個類使用了被 @Inherited 修飾的 Annotation, 則其子類將自動具有該註解
常用的是前兩種,瞭解了元註解後,下面把咱們的代碼加上元註解再試一下
package com.cj.study.annotation.app1;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)//註解存在於運行時
@Target(ElementType.METHOD)//說明MyTest註解只能用在方法上
public @interface MyTest {
}
package com.cj.study.annotation.app1;
public class DemoTest1 {
@MyTest
public void test1(){
System.out.println("test1執行了");
}
public void test2(){
System.out.println("test2執行了");
}
}
package com.cj.study.annotation.app1;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
//反射註解:
//取得類的字節碼
//反射其中的成員,此處就是方法成員
//看誰的上面有MyTest註解
//誰有,就執行誰
public class MyJunitRunner {
public static void main(String[] args) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
//取得類的字節碼
Class clazz = DemoTest1.class;
//反射其中的成員,此處就是方法成員
Method methods[] = clazz.getMethods();//得到DemoTest1中的所有公有的方法
//看誰的上面有MyTest註解
for(Method m:methods){
//誰有,就執行誰
boolean b = m.isAnnotationPresent(MyTest.class);
System.out.println(b+"==="+m.getName());
if(b){
m.invoke(clazz.newInstance(), null);
}
}
}
}
運行結果
發現test1方法執行了, test2方法沒執行,和預期的一樣。
OK,以上就是本人對註解的一些簡單的理解和總結,歡迎大家一起留言一起學習