Java 自定義註解

目錄

一、自定義Annotation

二、Java元註解

三、java.lang.annotation包

四、自定義Annotation的使用


一、自定義Annotation

先來看兩個自定義註解java文件:

1.JZDesc.java
package sn.test.test6.annotation;

import java.lang.annotation.*;

/**
 * 自定義Annotation:JZDesc
 */

@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JZDesc {
    public String value();
}
2.JZMethod.java 

 

package sn.test.test6.annotation;

import java.lang.annotation.*;

/**
 * 自定義Annotation:JZMethod
 */
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JZMethod {
    String name();
    String sex();
    int age();
}

看到這裏,你可能徹底蒙圈了,一上來就這麼晦澀, 可能你有很多疑問,比如:

  1. @interface是什麼意思?和interface關鍵字有什麼關係嗎?
  2.  Documented、Target、Retention 是神馬東東? 
  3.  ElementType、RetentionPolicy又是啥玩意兒?

不要着急,我下面會一一解答。

首先,@interface 也是一個關鍵字,和interface關鍵字沒有任何關係,僅僅說明要設計Annotation必須要指定類型爲@interface

其次,爲了更清楚的解釋上面(2)(3)東東的作用,不得不先來看看java的幾個原生註解

二、Java元註解

1.什麼是元註解?

-定義:作用於註解上的註解,白話就是:這些註解操作的對象還是註解。

2.常見的元註解有哪些?

-分類:@Document ,@Target ,@Retention ,@Inherited

3.元註解用來幹嘛的?

作用:
1. @Document :目的讓這個Annotation類型的信息可以顯示在javaAPI說明文檔中,如果不添加的話,使用javadoc生成 的接口文檔中將沒有這個類型生成的任何信息。
2. @Target:作用是指定這個Annotation可以用在哪些元素之上,如果不指定,則是ElementType枚舉值的最大範圍
3. @Retention:作用是指定這個Annotation的類型信息保留的範圍,如果不指定,則是RetentionPolicy枚舉值的最大範圍

解答了 Documented、Target、Retention 是神馬? 這個疑問,那麼再來看看第二個疑問:

ElementType、RetentionPolicy又是啥玩意? 要解釋這兩個問題,那就不得不提一個jar包:java.lang.annotation,具體往下看

三、java.lang.annotation包

java.lang.annotation包中有兩個源文件:ElementType.java,RetentionPolicy.java,下面來看下這兩個源文件的內容
1.ElementType.java 源文件
public enum ElementType {
    TYPE,
    FIELD,
    METHOD,
    PARAMETER,
    CONSTRUCTOR,
    LOCAL_VARIABLE,
    ANNOTATION_TYPE,
    PACKAGE
}
ElementType,一個enum類型,用來定義Annotation可以作用哪些元素上,有如下幾種:
*      1:TYPE(類型), 是指可以用在Class,Interface,Enum和Annotation類型上
*      2:FIELD(屬性),
*      3:METHOD(方法),
*      4:PARAMETER(參數),
*      5:CONSTRUCTOR(構造函數),
*      6:LOCAL_VARIABLE(局部變量),
*      7:ANNOTATION_TYPE,(註解)
*      8:PACKAGE(包)
2.RetentionPolicy 源文件
public enum RetentionPolicy {
    SOURCE,
    CLASS,
    RUNTIME
}
1. SOURCE-代表的是這個Annotation類型的信息只會保留在程序源碼裏,一旦編譯過後,Annotation的信息就會消失,不會出現在.class文件中
2. CLASS-表示這個Annotation類型的信息既保留在程序源碼裏,又保留在編譯後的.class文件中,但是執行時,不會被加載到JVM中
3. RUNTIME-表示這個Annotation類型的信息會分別保留在在源碼裏、編譯好的.class文件中,執行時也會被加載到JVM中

經過上面的講解,你可能大概瞭解上文中自定義Annotation文件 JZMethod.java 和JZDesc.java文件的大致內容,那麼又有一個疑問,自己一註解{}內部定義的比如 value() 是什麼?有什麼要注意的地方嗎嗎?

public @interface JZDesc {
    public String value();//參數成員1
}

public @interface JZMethod {
    String name();//參數成員1
    String sex();//參數成員2
    int age();//參數成員3
}

首先,Annotation內部定義的是註解的參數成員,如@Resource(name="aaa",description="方法1"),那麼name和description都是@Resource註解的參數成員,參數成員要指定參數的數據類型,如String,int,byte etc,並且可以用public修飾,也可以省略

其次,一般參數成員定義注意項有幾點:

1. 只能用public或默認(default)這兩個訪問權修飾.例如,String value();這裏把方法設爲defaul默認類型.
2. 參數成員只能用基本類型byte,short,char,int,long,float,double,boolean八種基本數據類型,String,Enum,Class,annotations等數據類型,以及這一些類型的數組.例如,String value();value()參數成員就爲String類型*      *      3.如果只有一個參數成員,最好把參數名稱設爲"value",後加小括號比如:String value();

ok,上面基本上全部解釋了自定義java文件中包含的內容代表的含義,那麼既然定義了兩個註解文件:JZDesc.java、JZMethod.java,那麼該如何應用呢?下面將簡單介紹如何將註解作用到其他類上

四、自定義Annotation的使用

1.AnnotationUsage.java  Annotation(JZDesc、JZMethod)使用示例

package sn.test.test6.annotation;

@JZDesc("這是本教主自定義的一個註解,作用元素Class")
public class AnnotationUsage {
    @JZMethod(name = "唐僧",sex = "男",age = 20)
    public String man(){
        return "這是一個人";
    }

    @JZMethod(name = "悟空",sex = "男",age = 500)
    public String monkey(){
        return "這是一隻成精的猴子";
    }

    @JZMethod(name = "沙僧",sex = "男",age = 1000)
    public String monster(){
        return "這是一個妖怪";
    }
}
2.Client.java 客戶端Annotation實際測試
package sn.test.test6.annotation;

import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;

public class Client {
    public static void main(String [] args) throws ClassNotFoundException {
        System.out.println("===開始測試了====");
        Class testClass=Class.forName("sn.test.test6.annotation.AnnotationUsage");
        Method[] methods=testClass.getMethods();
        /**
         * 1.獲取作用在Class上的JZDesc類型註解
         */
        //判斷JZDesc註解是否存在
        boolean flag=testClass.isAnnotationPresent(JZDesc.class);
        //存在
        if (flag){
            //獲取註解-getAnnotation()
            JZDesc jzDesc=(JZDesc)testClass.getAnnotation(JZDesc.class);
            //獲取參數成員
            System.out.println("JZDesc參數成員內容獲取爲:"+jzDesc.value());
        }
        /**
         * 2.獲取作用在Method上的JZMethod類型註解
         */

        //判斷哪些方法用了Name註解,如果用了,加入set中
        Set<Method> set = new HashSet<Method>();
        for(Method m:methods){
            boolean mflag=m.isAnnotationPresent(JZMethod.class);
            if (mflag){
                set.add(m);
            }
        }
        //一次輸出方法註解內容
        for (Method m:set){
            JZMethod method=(JZMethod)m.getAnnotation(JZMethod.class);
            if (method.age()==20){
                System.out.println("===人類===");
            }
            else if(method.age()==500){
                System.out.println("===猴子===");
            }
            else if(method.age()>500){
                System.out.println("===妖怪===");
            }
            System.out.println("外號:"+method.name()+",性別:"+method.sex()+",歲數:"+method.age());
        }
        System.out.println("===結束====");
    }

}

結果輸出:

 

截止到現在,你應該大致瞭解了Annotation的定義和使用了,當然java也有一些默認的Annotation類型,比如:@Override,@Deprecated,@SuppressWarnings,這裏就不一一介紹了,有興趣的話可以看看相關的資料信息

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章