java 註解使用詳解

概述

註解(Annotation),也叫元數據。一種代碼級別的說明。它是JDK1.5及以後版本引入的一個特性,與類、接口、枚舉是在同一個層次。它可以聲明在包、類、字段、方法、局部變量、方法參數等的前面,用來對這些元素進行說明,註釋。
作用:
1. 編寫文檔:通過代碼裏標識的元數據生成文檔【生成文檔doc文檔】
2. 代碼分析:通過代碼裏標識的元數據對代碼進行分析【使用反射】
3. 編譯檢查:通過代碼裏標識的元數據讓編譯器能夠實現基本的編譯檢查【Override】

註解介紹:

jdk內置註解:

在java.lang包下,JAVA提供了5個基本註解:
@Override
限定重寫父類方法。對於子類中被@Override 修飾的方法,如果存在對應的被重寫的父類方法,則正確;如果不存在,則報錯。@Override 只能作用於方法,不能作用於其他程序元素。
@Deprecated
用於表示某個程序元素(類、方法等)已過時。如果使用了被@Deprecated修飾的類或方法等,編譯器會發出警告。
@SuppressWarnings
抑制編譯器警告。指示被@SuppressWarnings修飾的程序元素(以及該程序元素中的所有子元素,例如類以及該類中的方法…..)取消顯示指定的編譯器警告。例如,常見的@SuppressWarnings(”unchecked”)
SuppressWarnings註解的常見參數值的簡單說明:
1、deprecation:使用了不贊成使用的類或方法時的警告(使用@Deprecated使得編譯器產生的警告);
2、unchecked:執行了未檢查的轉換時的警告,例如當使用集合時沒有用泛型 (Generics) 來指定集合保存的類型; 關閉編譯器警告
3、allthrough:當 Switch 程序塊直接通往下一種情況而沒有 Break 時的警告;
4、path:在類路徑、源文件路徑等中有不存在的路徑時的警告;
5、serial:當在可序列化的類上缺少 serialVersionUID 定義時的警告;
6、finally:任何 finally 子句不能正常完成時的警告;
7、all:關於以上所有情況的警告。
@SafeVarargs
@SafeVarargs是JDK 7 專門爲抑制“堆污染”警告提供的。

元註解說明:

點擊jdk自帶註解(SuppressWarnings)查看源碼如下:

package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {

    String[] value();
}

通過源碼我們發現@Target()和@Retention()兩個註解爲定義註解SuppressWarings使用的註解,我們稱這兩個爲元註解。
通過我們查jdk文檔發現,jdk常用的註解爲四個,這四個註解的功能和使用說明如下表:

名稱 說明
@Target ElementType.METHOD(更多值見下面ElementType類) 指定註解的作用域,class存在於類和接口上,Field作用於變量,Method作用於方法。
@Retention RetentionPolicy.RUNTIME (更多值見下面ElementType類) 指定註解的存在週期,Source註解信息只在源碼中存在;Class註解信息存在源碼,字節碼;RunTime註解信息存在源碼,字節碼,和運行時。
@Inherited 指定該註解在父類使用的時候,子類會繼成該註解。
@Documented 該註解表明這個註解應該被 javadoc工具記錄. 默認情況下,javadoc是不包括註解的. 但如果聲明註解時指定了 @Documented,則它會被 javadoc 之類的工具處理, 所以註解類型信息也會被包括在生成的文檔中.

jdk1.8 ElemenType枚舉類

public enum ElementType {
    /** Class, interface (including annotation type), or enum declaration */
    TYPE,
    /** Field declaration (includes enum constants) */
    FIELD,
    /** Method declaration */
    METHOD,
    /** Formal parameter declaration */
    PARAMETER,
    /** Constructor declaration */
    CONSTRUCTOR,
    /** Local variable declaration */
    LOCAL_VARIABLE,
    /** Annotation type declaration */
    ANNOTATION_TYPE,
    /** Package declaration */
    PACKAGE,
    /**
     * Type parameter declaration
     *
     * @since 1.8
     */
    TYPE_PARAMETER,
    /**
     * Use of a type
     *
     * @since 1.8
     */
    TYPE_USE
}

RetentionPolicy 類源碼

package java.lang.annotation;

public enum RetentionPolicy {
    /**
     * Annotations are to be discarded by the compiler.
     */
    SOURCE,

    /**
     * Annotations are to be recorded in the class file by the compiler
     * but need not be retained by the VM at run time.  This is the default
     * behavior.
     */
    CLASS,
    /**
     * Annotations are to be recorded in the class file by the compiler and
     * retained by the VM at run time, so they may be read reflectively.
     *
     * @see java.lang.reflect.AnnotatedElement
     */
    RUNTIME
}
自定義註解:

自定義註解類編寫的一些規則:
1. Annotation型定義爲@interface, 所有的Annotation會自動繼承java.lang.Annotation這一接口,並且不能再去繼承別的類或是接口。
2. 參數成員只能用public或默認(default)這兩個訪問權修飾。
3. 參數成員只能用基本類型byte,short,char,int,long,float,double,boolean八種基本數據類型和String、Enum、Class、annotations等數據類型,以及這一些類型的數組.。
4. 註解也可以沒有定義成員。
自定義註解需要使用到元註解,獲取註解信息可以通過APT(Annotation Processing Tool)獲取。在jdk中也可以通過反射獲取@Retention爲RetentionPolicy.RUNTIME(運行期間)的註解信息。

反射獲取註解信息:

自定義註解:RStudent.java

package anno;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Documented
@Retention(RUNTIME)
@Target(TYPE)
public @interface RStudent {

    int _id() default 0;

    String _name() default "";

    String _address() default "";

}

javaBean文件:

package model;

import anno.RStudent;

@RStudent(_id =1,_name="zhangwenwen",_address="beijing")
public class Student {

    public int id;

    public String name;

    public String address;


}

測試代碼:

package main;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;


import model.Student;
/**
 * 
 * @author 53048
 *
 */
public class TestReflection {


    public static void main(String args []){

        //反射獲取註解
        testAnno(Student.class);


    }


    private static <T> void testAnno(Class<T> classs) {
        // TODO Auto-generated method stub
        System.out.println("------------------------------------------------------------------------");
        System.out.println("測試註解:");
        T object = null;
        try {
            object = classs.newInstance();
        } catch (InstantiationException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

         Annotation[] annos = classs.getDeclaredAnnotations();

        for(Annotation anno:annos){
            System.out.println(anno);
            if(anno instanceof RStudent){

                RStudent students = (RStudent)anno;
                Student stu= (Student)object;
                stu.id = students._id();
                stu.address = students._address();
                stu.name = students._name();

                System.out.println("學生的Id:"+stu.id);
                System.out.println("學生的name:"+stu.name);
                System.out.println("學生的address:"+stu.address);

            }
        }
    }

這裏寫圖片描述

希望對您有所幫助!

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