5分鐘帶你入門Java註解annotation

 

包 java.lang.annotation 中包含所有定義自定義註解所需用到的原註解和接口。
接口 java.lang.annotation.Annotation 是所有註解繼承的接口,並且是自動繼承,不需要定義時指定,類似於所有類都自動繼承Object。 
該包同時定義了四個元註解,
Documented
註解表明這個註解應該被 javadoc工具記錄. 默認情況下,javadoc是不包括註解的. 但如果聲明註解時指定了 @Documented,則它會被 javadoc 之類的工具處理, 所以註解類型信息也會被包括在生成的文檔中.
Target(作用範圍,方法,屬性,構造方法等),
用來聲明註解可以被添加在哪些類型的元素上,如類型、方法和域等。
Retention(生命範圍,源代碼,class,runtime)。
用來聲明註解的保留策略,有CLASS、RUNTIME和SOURCE這三種,
分別表示註解保存在類文件、JVM運行時刻和源代碼中。只有當聲明爲RUNTIME的時候,才能夠在運行時刻通過反射API來獲取到註解的信息。
Inherited : 在您定義註解後並使用於程序代碼上時,預設上父類別中的註解並不會被繼承至子類別中,
您可以在定義註解時加上java.lang.annotation.Inherited 限定的Annotation,這讓您定義的Annotation型別被繼承下來

1.作用

(1)生成文檔。也是最常見的,常用的有@see @param @return等
(2)替代配置文件。spring 2.5以後開始基於註解開發,現在的框架基本上都用了註解減少配置文件。【spring4.x註解概述】有具體的說明。
(3)編譯時進行格式檢查。 如@Override 放在方法前,如果你這個方法並不是覆蓋了超類方法,則編譯時就能檢查出。
 

2.自定義註解用法

(1)建一個註解@interface TestA
package com.annotationTest;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.RetentionPolicy;
@Target(value = {ElementType.TYPE,ElementType.METHOD,ElementType.FIELD,ElementType.CONSTRUCTOR}) 
@Retention(RetentionPolicy.RUNTIME)
public @interface TestA {
    String name();
    int id() default 0;
    Class<Long> gid();
}
(2)寫一個類UserAnnotation 來使用@TestA
package com.annotationTest;
import java.util.ArrayList;
import java.util.List;
@TestA(name="type",gid=Long.class) //類成員註解
public class UserAnnotation {

    @TestA(name="param",id=1,gid=Long.class) //類成員註解
    private Integer age ;

    @TestA (name="construct",id=2,gid=Long.class)//構造方法註解
    public UserAnnotation() {
    }

    @TestA(name="public method",id=3,gid=Long.class) //類方法註解
    public void functionA(){
        List list = new ArrayList();
    }
    @TestA(name="protected method",id=4,gid=Long.class) //類方法註解
    public void functionB(){
        List list = new ArrayList();
    }

    @TestA(name="private method",id=5,gid=Long.class) //類方法註解
    public void functionC(){
        List list = new ArrayList();
    }
 }
(3)簡單打印出UserAnnotation 類中所使用到的類註解
jdk反射機制
public interface AnnotatedElement {
        boolean isAnnotationPresent(Class<? extends Annotation> annotationClass);
        <T extends Annotation> T getAnnotation(Class<T> annotationClass);
        Annotation[] getAnnotations();
        Annotation[] getDeclaredAnnotations();
}
isAnnotationPresent:判斷是否標註了指定註解
getAnnotation:獲取指定註解,沒有則返回null
getAnnotations:獲取所有註解,包括繼承自基類的,沒有則返回長度爲0的數組
getDeclaredAnnotations:獲取自身顯式標明的所有註解,沒有則返回長度爲0的數組

package com.annotationTest;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class ParseAnnotation {
    public static void parseTypeAnnotation() throws ClassNotFoundException{
     Class clazz = Class.forName("com.annotationTest.UserAnnotation");
     Annotation[] annotations = clazz.getAnnotations();
     for (Annotation annotation : annotations) {
        TestA testA = (TestA) annotation;
        System.out.println("id = "
                            +testA.id()
                            +"\t name = "
                            +testA.name()
                            +"\t gid = "
                            +testA.gid()
                            );
    }
 }
    private static void parseConstructAnnotation() {
        Constructor[] constructors = UserAnnotation.class.getConstructors();
        for (Constructor constructor : constructors) {
            boolean hasAnnotation = constructor.isAnnotationPresent(TestA.class);
            if (hasAnnotation) {
                TestA annotation = (TestA) constructor.getAnnotation(TestA.class);
                System.out.println("constructor  : "
                                    +constructor.getName()
                                    +"\t id = "
                                    +annotation.id()
                                    +"\t name = "
                                    +annotation.name()
                                    +"\t gid = "
                                    +annotation.gid()
                                    );
            }
        }
    }
    private static void parseMethodAnnotation() {
        Method[] methods = UserAnnotation.class.getDeclaredMethods();         
        for (Method method : methods) {
               /*
             * 判斷方法中是否有指定註解類型的註解
             */ 
            boolean hasAnnotation = method.isAnnotationPresent(TestA.class);
            if (hasAnnotation) {
                TestA annotation = method.getAnnotation(TestA.class);
                System.out.println("method : "
                                    +method.getName()
                                    +"\t id = "
                                    +annotation.id()
                                    +"\t name = "
                                    +annotation.name()
                                    +"\t gid = "
                                    +annotation.gid()
                                    );
            }
        }
    }
    public static void main(String[] args) throws ClassNotFoundException {
        parseTypeAnnotation();
        parseConstructAnnotation();
        parseMethodAnnotation();
    }
}
 
 

3.建議

(1) 不要濫用註解。首先強烈建議學習好框架裏出現的註解,按照框架規定的方式使用。
(2) 不要濫用註解。平常我們編程過程很少接觸和使用註解,只有做設計,且不想讓設計有過多的配置時。
(3) 要用好註解,必須熟悉java 的反射機制,從上面的例子可以看出,註解的解析完全依賴於反射。
    
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章