1. 程式人生 > >註解基礎篇:自定義Java Annotation

註解基礎篇:自定義Java Annotation

## 寫在前面

JDK5增加了對Annotation(註解)的支援,Annotation是程式碼裡的特殊標記,這些標記可以在編譯,類載入和執行時被讀取讀取出來,並執行相應的處理和操作!比如在不改變程式邏輯的情況下,開發人員可以在程式碼中嵌入一些補充資訊,程式碼分析和開發部署工具APT(AnnotationProcessTool)可以通過這些資訊進行驗證或部署。

APT工具在處理註解時,會根據原始檔的Annotation資訊,生成附加原始檔或者進行一些其他操作!最後在車鞥徐編譯時期,APT會將生成的附加原始檔和原有原始檔進行合併,生成最終的*.class檔案!預設情況下,Annotation可以修飾任何程式元素(ElementType),包括類,介面,成員方法,成員變數。根據Annotation是否帶成員變數,可分為兩類:

  • 標記Annotation,根據自身存在與否提供資訊;
  • 元資料Annotation,根據接收的成員變數值,提供元資料資訊;

## 設計Annotation

與定義一個介面很相似,自定義Annotation使用@interface關鍵字:

//字元定義Annotation
public @interface CustomAnno {
}

//使用上面自定義的Annotaiton,修飾類
@CustomAnno
public class BeautifulClass {
    //修飾成員方法
    @CustomAnno
    public void toPlus() {...}
}

Annotation也可以有成員變數,如下定義:

public @interface HelloAnno {
    //定義帶兩個成員變數的Annotation
    //Annotaion中的成員變數以方法的形式來定義
    String apple();
    Integer pear();
}

//使用帶成員變數的Annotation
public class beautifulClass2 {
    //需要為成員變數賦值
    @HelloAnno(apple="apple", pear=101)
    public void toPlus() {...}
}

當然,帶成員變數的Annotation也可以為期指定初始值(預設值),在哪在使用註解的時候就不需要再次未改成員變數賦值了;當然,如果需要的話也可以再次賦值,則新值會覆蓋預設值!如下:

public @interface BlackAnno {
    //定義帶兩個成員變數的Annotation
    //Annotaion中的成員變數以方法的形式來定義
    //指定成員變數的預設值,使用default關鍵字
    String apple() default "black";
    Integer pear() default 101;
}

//使用帶成員變數的Annotation
public class beautifulClass3 {
    //@HelloAnno已經指定了預設值
    //則使用時不需要賦值,直接使用即可
    @HelloAnno
    public void toPlus1() {...}
    
    //如果需要,也可以為成員變數賦值,則會覆蓋預設值
    @HelloAnno(apple="apple", pear=101)
    public void toPlus2() {...}
}

## 提取Annotation

使用Annotation修飾了類以及成員方法後,這些Annotation不會自己生效,必須有開發者提供相應的工具來提取並處理Annotation資訊。

java.lang.reflect包下包含一些實現反射功能的工具類:比如定義Annotation時使用@Rentation(RetentionPolicy.RUNTIME)修飾,則Annotation會被編譯器儲存在*.class檔案中,Java在執行時會通過反射讀取類檔案中的Annotation!

AnnotatedElement介面是所有程式元素(Class,Method,Constructor等)的父介面,所以獲得某個AnnotationElement物件後,就可以呼叫該物件的如下方法來訪問Annotation註解資訊:

  • <T extends Annotation> T getAnnotation(Class<T> annotationClass)
  • Annotation[] getAnnotations()
  • default <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass)
  • default <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass)
  • Annotation[] getDeclaredAnnotations()
  • default <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass)
  • default boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)

## 自定義註解demo

自定義一個Java註解 @CustomAnno,程式碼如下:

/**
 * 自定義一個 Java 註解
 *  1. @Retention(RetentionPolicy.RUNTIME)
 *      執行時讀取並處理註解資訊
 *  2. @Target(ElementType.METHOD)
 *      自定義註解只能修飾方法
 *
 * Created by wondertwo on 2016/10/16.
 */
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CustomAnno {}

用以上自定義的註解,來修飾Person類的八個方法,程式碼如下:

/**
 * Created by wondertwo on 2016/10/16.
 */
public class Person {
    /**
     * 使用自定義註解 @CustomAnno 修飾以下 8個方法
     */
    @CustomAnno
    public static void method_1() {}
    @CustomAnno
    public static void method_2() {}
    @CustomAnno
    public static void method_3() {}
    @CustomAnno
    public static void method_4() {}
    @CustomAnno
    public static void method_5() {}
    @CustomAnno
    public static void method_6() {}
    @CustomAnno
    public static void method_7() {}
    @CustomAnno
    public static void method_8() {}
}

測試註解,通過反射呼叫方法,程式碼如下:

/**
 * Created by wondertwo on 2016/10/16.
 */
public class AnnoTest {
    public static void main(String[] args) throws ClassNotFoundException {
        process("me.wondertwo.annotation.Person"); //Person
    }
    private static void process(String clazz) throws ClassNotFoundException {
        int passed= 0 , failed = 0;
        //遍歷clazz對應類的所有方法
        for (Method method : Class.forName(clazz).getMethods()) {
            //如果該方法使用了自定義註解 @CustomAnno 修飾
            if (method.isAnnotationPresent(CustomAnno.class)) {
                try {
                    method.invoke(null);
                    passed++;
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("方法 " + method + " 測試失敗,出現異常");
                    failed++;
                }
            }
        }
        System.out.println("一共運行了 " + (passed+failed) + " 個方法");
        System.out.println("成功執行方法 " + passed + " 個");
        System.out.println("失敗執行方法 " + failed + " 個");
    }
}
/**
 * 執行結果輸出如下:
 * 一共運行了 8 個方法
 * 成功執行方法 8 個
 * 失敗執行方法 0 個
 * Process finished with exit code 0
 */

我們的自定義註解,成功的被提取出來並執行了!

相關推薦

註解基礎定義Java Annotation

## 寫在前面 JDK5增加了對Annotation(註解)的支援,Annotation是程式碼裡的特殊標記,這些標記可以在編譯,類載入和執行時被讀取讀取出來,並執行相應的處理和操作!比如在不改變程式邏輯的情況下,開發人員可以在程式碼中嵌入一些補充資訊,程式碼分析和開發部署工具APT(AnnotationP

註解提高定義註解處理器(APT)

## 0x01 繼承AbstractProcessor抽象類 當定義好Annotation註解後,接下來就需要一個註解處理器來處理我們的自定義註解了。實現Java Annotation一般需要繼承AbstractProcessor抽象類,並且重寫其四個方法來實現提取,解析並處理自定義註解的邏輯如下: cla

定義 Java Annotation ,讀取註解

sta tools stp exc num value mage test lang 1. 首先是自定義註解: Java代碼 package cn.veji.hibernate.po; import java.lang.annot

分享定義JAVA註解

http ack 信息 element 常量 變量 分享 oca runt   元註解   元註解指用來定義註解的註解,例如:@Retention @Target Inherited @Documented等等。最為重要和經常使用的是@Retention @Target。

基礎深入解析JAVA註解機制

[TOC](目錄標題) # java實現註解的底層原理和概念 - java註解是JDK1.5引入的一種註釋機制,java語言的類、方法、變數、引數和包都可以被註解標註。和Javadoc不同,java註解可以通過反射獲取標註內容 - 在編譯器生成.class檔案時,註解可以被嵌入位元組碼中,而jvm也可以保

ArcGIS Engine 開發學習-------基礎(一)定義命令

 要求:在ToolbarControl中新增一個自定義命令,點選可清除當前活動工具。     步驟: 1、建立GIS類,選擇Base Command模版,Extending ArcObjects,ArcMap MapControl or PageLayo

精通Spring Boot——第十八定義認證流程

前兩篇簡單介紹了一下使用Spring Security 使用Http Basic登入,以及Spring Security如何自定義登入邏輯。這篇文章主要介紹如何使用handler來定義認證相關的流程。 先做一些自定義的操作,如配置自定義登入頁,配置登入請求URL等。 當我們使用Spring Security時

MySQL 第八定義函式、儲存過程、遊標

本篇內容由猿道教育的課程內容整理而來。 我把MySQL的內容整理成9篇部落格,學完這9篇部落格雖不能說能成為大神,但是應付一般中小企業的開發已經足夠了,有疑問或建議的歡迎留言討論。 自定義函式 一、函式的概念與定義 1、理解函式 函式可以看作是

【tensorflow】基礎定義layer並新增到計算圖中

目的 將使用者自定義的layer結合tensorflow自帶的layer組成多層layer的計算圖。 實現功能 對2D影象進行滑動視窗平均,並通過自定義的操作layer返回結果。 import

Android特效第三定義Gallery實戰(仿網易) .

Android系統提供了一個Gallery畫廊控制元件,在專案很多時候都會用到Gallery,比如新浪首頁的廣告,網易看客戶端首頁等隨處可見,今天我自己定義了一個仿網易的Gallery與大家共享。      首先請看效果圖:                        

Web開發之-JSP學習總結-第四定義標籤總結

一、自定義標籤開發步驟—以高仿<c:if test=""></c:if>標籤為例 1、編寫一個普通的java類,繼承SimpleTagSupport類,叫標籤處理器類。並且覆蓋doTag方法 /** * 標籤處理器類 * 1)繼承

SpringBoot第十六定義starter

作者:追夢1819 原文:https://www.cnblogs.com/yanfei1819/p/11058502.html 版權宣告:本文為博主原創文章,轉載請附上博文連結! 前言   這一段時間專案趕進度,故該系列部落格更新沒有之前那麼頻繁,望諒解。   SpringBoot 用起來方便,它預設集成了

Spring Boot 基礎系列教程 | 第三十二使用@Async實現非同步呼叫定義執行緒池

推薦 Spring Boot/Cloud 視訊: 在之前的Spring Boot基礎教程系列中,已經通過《Spring Boot中使用@Async實現非同步呼叫》一文介紹過如何使用@Async註解來實現非同步呼叫了。但是,對於這些非同步執行的控制是我們保障自身

Unity Editor 基礎(二)定義 Inspector 面板

自定義Inspector屬性面板 EditorGUILayout 編輯器介面佈局  這是一個編輯器類,如果想使用它你需要把它放到工程目錄下的Assets/Editor資料夾下。編輯器類在UnityEditor名稱空間下。所以當使用C#指令碼時,你需要在指令碼前面加上

Unity Editor 基礎(三)定義視窗案例二

本文為本人學習上鍊接的筆記微有改動,請點選以上鍊接檢視原文,尊重樓主智慧財產權。 ----------------------------------------------------------------------------------------------

定義Java註解annotation

https://www.imooc.com/learn/456  筆記 Java從1.5開始引進註解。 首先解決一個問題,為什麼要學習Java註解? 1.看懂別人寫的程式碼,尤其是框架的程式碼 2.可以是自己寫的程式碼簡潔清晰   現在開始學習Java註解了。  

Java註解定義註解示例,利用反射進行解析

        Java註解能夠提供程式碼的相關資訊,同時對於所註解的程式碼結構又沒有直接影響。在這篇教程中,我們將學習Java註解,如何編寫自定義註解,註解的使用,以及如何使用反射解析註解。        註解是Java 1.5引入的,目前已被廣泛應用於各種Java框

Android零基礎入門第24節定義View簡單使用

子類 protect jin 討論 我們 @+ amp 進階 運行程序 當我們開發中遇到Android原生的組件無法滿足需求時,這時候就應該自定義View來滿足這些特殊的組件需求。 一、概述 很多初入Android開發的程序員,對於Android自定義View可能比較

Android零基礎入門第40節定義ArrayAdapter

出發點 ppc vsa abs 顯示 osi adc this launcher ListView用起來還是比較簡單的,也是Android應用程序中最重要的一個組件,但其他ListView可以隨你所願,能夠完成很多想要的精美列表,而這正是我們接下來要學習的內容。

visual studio code教程基礎使用和定義設置

麻煩 安裝 顏色 必須 寫入 全局環境變量 註意 一個 preview 一、界面介紹 1.1 界面介紹 1.2 文件夾和文件的打開 文件——>打開文件夾/打開文件 1.3 新建文件/文件夾 新建文件: a. 文件——>新建文件; b. 按Ctrl+n; c