java自定義註解

一、註解按照運行機制分類:

源碼註解:註解只在源碼中存在,.class文件就沒了
編譯時註解:註解在源碼和.class文件裏都存在(@Override、@Deprecate)
運行時註解:程序運行時還起作用(@Autowired)

二、註解按照使用的方式和用途分類。

(1)內建註解

又稱爲基本註解,位於java.lang包下。
內建註解有三個:
1、檢驗重寫父類方法:@Override
2、標識方法已經過時:@Deprecated
3、取消編譯器警告:@SurppressWarnings

(2)元註解

元註解就是在註解上添加的註解。
位置:元註解位於java.lang.annotation子包中。
作用:用於修飾其他註解。
元註解有四個:
@Retention,@Target,@Documented,@Inherited
Java SE 8引入@Repeatable元註解,表示註解可以重複使用(同一個方法或類上重複使用)

(3)自定義註解

需要用到關鍵字@interface來定義

三、自定義註解

/**
 * @author: lizhilong
 * @date: 2017-12-05 10:50:54
 */
// 元註解
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Sign {
    // 成員以無參無異常的方式聲明
    String sign();

    String author() default "";

    int age() default 18;
}

注意:
1、成員類型只能是基本類型、String、Class、Annotation、Enumeration這幾個
2、如果註解只有一個成員,則成員名必須(約定俗成)取名爲value()
3、註解可以沒有成員,沒有成員的註解成爲標識註解
4、如果成員沒有默認值,則使用的時候必須要填

四、元註解的作用:

@Retention:用來描述被修飾的註解的生命週期。
@Target:用於指定被修飾的註解的適用範圍,即被修飾的註解可以用來修飾哪些程序元素。
@Documented:用於指定被修飾的註解將被javadoc工具提取成文檔。
@Inherited:用於指定被@Inherited修飾的註解具有繼承性。
@Retention 中參數
@Retention(RetentionPolicy.SOURCE):註解僅存在於源碼中,在class字節碼文件中不包含
@Retention(RetentionPolicy.CLASS):默認的保留策略,註解會在class字節碼文件中存在,但運行時無法獲得
@Retention(RetentionPolicy.RUNTIME):註解會在class字節碼文件中存在,在運行時可以通過反射獲取到
@Target中參數
@Target(ElementType.TYPE):              接口、類、枚舉、註解
@Target(ElementType.FIELD):             字段、枚舉的常量
@Target(ElementType.METHOD):            方法
@Target(ElementType.PARAMETER):         方法參數
@Target(ElementType.CONSTRUCTOR):       構造函數
@Target(ElementType.LOCAL_VARIABLE):    局部變量
@Target(ElementType.ANNOTATION_TYPE):   註解
@Target(ElementType.PACKAGE):           包  

五、註解的使用

自定義註解使用的類:
/**
 * @author: lizhilong
 * @date:   2017-12-05 16:58:29   
 */
@Sign(author = "lizhilong", sign = "class sign")
public class Teacher implements Person {

    @Override
    @Sign(author = "lizhilong", sign = "method sign")
    public void eat() {
        System.out.println("吃了....");
    }

}
註解獲取:
package vip.lizhilong.lambda.test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

import org.junit.Test;
import vip.lizhilong.lambda.annotation.Sign;
/**
 * @author: lizhilong
 * @date:   2017-12-05 17:02:12   
 */
public class AnnotationTest {

    @SuppressWarnings({"rawtypes", "unchecked"})
    @Test
    public void Test(){
        try {
            // 1.使用類加載器
            Class clazz = Class.forName("vip.lizhilong.lambda.impl.Teacher");
            // 2.找到類上的註解(兩種)
            // 第一種方式
            boolean isExit = clazz.isAnnotationPresent(Sign.class);
            if (isExit) {
                // 3.拿到註解實例
                Sign sign = (Sign)clazz.getAnnotation(Sign.class);
                System.out.println(sign.author() + "----" + sign.sign() + "----" + sign.age());
            }

            // 第二種方式
            Annotation[] annotations = clazz.getAnnotations();
            for (Annotation annotation : annotations) {
                // instanceof 判斷是否爲父子關係,也可以判斷類型
                if (annotation instanceof Sign) {
                    Sign sign = (Sign) annotation;
                    System.out.println(sign.author() + "----" + sign.sign() + "----" + sign.age());
                }
            }

            // 4.找到方法上的註解
            Method[] methods = clazz.getMethods();
            for (Method method : methods) {
                isExit = method.isAnnotationPresent(Sign.class);
                if (isExit) {
                    Sign sign = method.getAnnotation(Sign.class);
                    System.out.println(sign.author() + "----" + sign.sign() + "----" + sign.age());
                }
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}
打印結果
lizhilong----class sign----18
lizhilong----class sign----18
lizhilong----method sign----18

這些事註解的創建和使用的基本方式,
應用場景:登陸、權限攔截、定時任務管理
下篇會講註解在項目中的使用
如何在在項目中使用自定義註解

發佈了29 篇原創文章 · 獲贊 24 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章