1. 程式人生 > >Java語言使用註解處理器生成程式碼 —— 第一部分:註解型別

Java語言使用註解處理器生成程式碼 —— 第一部分:註解型別

原文作者:deors
原文地址:https://deors.wordpress.com/2011/09/26/annotation-types/
譯文作者:Jianan - [email protected]
版本資訊:本文基於2015-10-09版本進行翻譯
版權宣告:經原作者許可進行翻譯,保留所有權利,未經允許不得複製和轉載。


從本文開始,我將開始寫一系列關於Java語言使用註解處理器生成程式碼的文章,包括這種方法的強大之處。最後還會描述如何確保在編譯的時候使用這種方法生成原始碼。

在這系列文章中,我們將會:

  • 介紹Java語言的註解。
  • 瞭解註解的常用方式以及使用範圍。
  • 瞭解註解處理器以及它們所代表的角色。
  • 學習如何建立註解處理器。
  • 學習如何在終端命令列、Eclipse和Maven中執行註解處理器。
  • 學習如何使用註解處理器生成原始碼。
  • 學習如何使用像Apache Velocity這樣的外部模板引擎來使用註解處理器生成原始碼。

Java的註解從第三版的Java語言規範(1)中開始引入,並在Java 5中開始支援。

通過註解,我們可以為原始碼新增元資料資訊,包括編譯或部署資訊、配置屬性、編譯行為或者程式碼質量檢查。

與Javadoc不同,註解屬於強型別,用到的註解在類路徑下都能找到對應的註解型別定義。因此,定義的註解可以在執行時訪問到,而Javadoc是不可能的。

註解語法

註解通常出現在被註解的程式碼段前面,通常情況下都是獨立成行並且與程式碼段同樣縮排。

註解可以新增到package(包)、types(型別,包括類、介面、列舉和其它註解型別)、variable(變數、包括class、類例項、區域性變數——包括定義在for或者while迴圈裡面的區域性變數)、constructions(構造方法)、methods(方法)和parameters(引數)。

最簡單的註解結構就是內部什麼元素都沒有,例如:

@Override()
public void theMethod() {…}

在這個例子中,括號可以省略(因為沒有引數):

@Override
public void theMethod() {…}

註解也可以包含元素,這些元素是通過逗號分隔的鍵值對。允許使用的值型別包括java原生資料型別、String型別、列舉型別,以及這些型別的陣列形式:

@Author(name = "Albert",
        created = "17/09/2010",
        revision = 3,
        reviewers = {"George", "Fred"})
public class SimpleAnnotationsTest {…}

當註解內部只有一個元素,並且這個元素名為value的時候,元素名可以省略:

@WorkProduct("WP00000182")
@Complexity(ComplexityLevel.VERY_SIMPLE)
public class SimpleAnnotationsTest {…}

註解可以為內部一些元素或者全部元素都設定預設值。在使用這類註解的時候,具備預設值的元素可以省略。

例如,假設有個註解為Author,它為內部元素revision(預設為1)以及reviewers(預設為空String陣列)設定了預設值,下面使用這個註解的兩種方式是等效的:

@Author(name = "Albert",
        created = "17/09/2010",
        revision = 1,
        reviewers = {})
public class SimpleAnnotationsTest() {…}
@Author(name = "Albert",        // defaults are revision 1
        created = "17/09/2010") // and no reviewers
public class SimpleAnnotationsTest() {…}

註解的典型使用

Java語言規範中定義了三種註解型別——它們都用於Java編譯器:

  • @Deprecated: 用來宣告被註解的元素不應該再使用。每當這個註解被使用的時候,編譯器就會生成一個警告。它應該與Javadoc的@deprecated一起使用,在Javadoc中解釋捨棄被註解元素的原因。

  • @Override: 用來宣告被註解的元素重寫了父類中宣告的元素。如果被註解的元素沒有在父類中找到對應的被重寫的元素,編譯器就會生成一個警告。儘管這個註解沒有要求一定要使用,但是它對於錯誤判斷非常有用——例如,如果在建立父類之後,有人又修改了父類方法的簽名,那麼我們在重新編譯原始碼的時候就能馬上得到提醒。

  • @SuppressWarnings: 讓編譯器抑制指定的警告型別,否則被註解的元素就會觸發這類警告——例如,為了避免使用了被捨棄的API或者與舊程式碼(例如Java 5之前的版本)進行了未檢查的互動而產生過多的編譯器“干擾”。

自從引入這些註解後,很多庫和框架都將註解整合到它們新的發行版本中。通過在原始碼中使用註解,這些庫和框架都簡化甚至移除了所需要的配置檔案。

下面是一些成功使用註解的例子:

  • Java企業版和它的主要模組——企業級JavaBeans、Java持久化API或者Web Service API。
  • Spring框架——用於核心模組中的配置、依賴註解和控制反轉中,以及其它一些Spring專案。
  • Sean、Weld、Guice.
  • Apache Struts 2.

註解型別

在Java語言中註解型別是一種特殊的介面,用來自定義註解。

註解的定義要使用@interface關鍵字來代替interface

public @interface Author {
    String name();
    String created();
    int revision() default 1;
    String[] reviewers() default {};
}
public @interface Complexity {
    ComplexityLevel value() default ComplexityLevel.MEDIUM;
}
public enum ComplexityLevel {
    VERY_SIMPLE, SIMPLE, MEDIUM, COMPLEX, VERY_COMPLEX;
}

註解型別與普通的介面有一些區別:

  • 只允許原生資料型別、String、列舉、class,以及這些型別的陣列。注意註解型別中不允許常用的物件,也不允許陣列的陣列(因為每一個數組都是一個物件)。

  • 註解元素的定義與定義方法的語法很類似,但是不允許有修飾符和引數。

  • 註解元素的預設值定義需要使用default關鍵字,後面連線字面量、初始化陣列或者列舉值。

正如其它的類或者介面,列舉型別也可以巢狀在註解型別的內部:

public @interface Complexity {
    public enum Level {
        VERY_SIMPLE, SIMPLE, MEDIUM, COMPLEX, VERY_COMPLEX;
    }
    …
}

用於定義註解的註解

JDK自帶了一些註解,用於修改我們自定義的註解的預設行為。

  • @Documented: 宣告被@Documented註解後的註解型別,一旦使用,被註解的元素就應該連同註解都記錄到Javadoc中。

  • @Inherited: 宣告被註解的註解型別能夠繼承到它的子類上。通過這種方法,如果當前子類沒有受@Inherited註解的註解型別註解過,但是它的父類有,那麼當前子類也能通過繼承得到這個註解型別。不過它只適用於類繼承,不適用於介面實現。

  • @Retention: 宣告被註解的註解型別生命週期。可選的值都包含在RetentionPolicy列舉中:CLASS(預設值——能被包含到class檔案中,但是在執行時訪問不到),SOURCE(建立class檔案的時候會被編譯器丟棄),RUNTIME(能夠在執行過程中訪問到)。

  • @Target: 宣告註解型別能夠註解的元素型別。可選的值包含在ElementType列舉中:ANNOTATION_TYPE(用於註解型別),CONSTRUCTOR(用於構造方法),FIELE(用於成員變數),LOCAL_VARIABLE(用於區域性變數),METHOD(用於方法),PACKAGE(用於包),PARAMETER(用於方法引數),TYPE(用於類、介面、列舉)。

本系列將會在第二部分中繼續講解:註解處理器。請閱讀這裡.

相關推薦

Java語言使用註解處理器生成程式碼 —— 第一部分註解型別

原文作者:deors 原文地址:https://deors.wordpress.com/2011/09/26/annotation-types/ 譯文作者:Jianan - [email protected] 版本資訊:本文基於

自定義註解處理器生成程式碼.md

自定義註解處理器生成程式碼 先上一段程式碼: public class MainActivity extends AppCompatActivity { @BindView(R.id.tv) TextView tv; @Bi

Java密碼學原型演算法實現——第一部分標準Hash演算法

題注 從部落格中看出來我是個比較鍾愛Java的應用密碼學研究者。雖然C在密碼學中有不可替代的優勢:速度快,但是,Java的可移植性使得開發人員可以很快地將程式碼移植到各個平臺,這比C實現要方便的多。尤其是Android平臺的出現,Java的應用也就越來越廣。因此,我本人在密

使用java語言中的註解生成器生成程式碼

Code Generation using Annotation Processors in the Java language – part 1: Annotation Types 註解型別 這篇帖子我會開始關於使用java語言中註解處理器來程式碼生

Java編譯時註解自動生成程式碼

在開始之前,我們首先申明一個非常重要的問題:我們並不討論那些在執行時(Runtime)通過反射機制執行處理的註解,而是討論在編譯時(Compile time)處理的註解。註解處理器是一個在javac中的,用來編譯時掃描和處理的註解的工具。可以為特定的註解,註冊自己的註解處

【區塊鏈Go語言實現】第一部分區塊鏈基本原型

ont 構建 獲得 列表 append 檢查 世紀 正常 私有 0x00 介紹 區塊鏈(Blockchain)是21世紀最具革命性的技術之一,目前它仍處於逐漸成熟階段,且其發展潛力尚未被完全意識到。從本質上講,區塊鏈只是一種記錄的分布式數據庫。但它之所以獨特,是因為它並

Object Detection (3)Faster RCNN Keras 原理+程式碼 第一部分

目錄        Object Detection (1)VOC2007資料集製作        Object Detection (2)Faster RCNN詳解     &

Java語言實現hello world程式碼

24種程式語言的Hello World程式 Java 文件註釋 Java 支援三種註釋方式。前兩種分別是 // 和 /* */,第三種被稱作說明註釋,它以 /** 開始,以 */結束。 說明註釋允許你在程式中嵌入關於程式的資訊。你可以使用 javadoc 工

雜湊三部曲第一部分C語言實現 靜態雜湊表

在這個靜態雜湊表中 我們用一個容量為10 的靜態陣列作為雜湊表的底層構造 但是陣列的每一個儲存空間中又分為兩個部分                                 資料區:data                                    

java語言基礎認識及程式碼實踐

基本資料型別 變數 基本型別變數 資料型別的轉換規則 運算子 Java語言中的資料型別分為兩大型別: 一、基本資料型別。 1、基本資料型別是由程式設計語言系統所定義、不可再劃分的資料型別。 每種基本資料型別的資料所佔用記憶體的大小是固定的,與軟硬體環境無關

浙大《java語言》學習筆記(第一週)

1.1用類製造物件      1.2定義類 這裡我們定義了一個類 這裡我們寫一個VendingMachine的類 package vendingmachine; public class VendingMachine { i

AbstractProcessor: 利用註解動態生成程式碼

按照處理時期,註解分為兩種型別,一種是執行時註解,另一種是編譯時註解。 編譯時註解的核心依賴APT(Annotation Processing Tools)實現,對應的處理流程為: 在某些程式碼元素上(如型別、函式、欄位等)添加註解; 編譯時編譯器會檢查A

人工智慧-智慧創意平臺架構成長之路(四)-豐富多彩的banner圖生成解密第一部分--如何做出阿里鹿班一樣的banner圖

人工智慧-智慧創意平臺架構成長之路(一)--長篇開篇 人工智慧-智慧創意平臺架構成長之路(二)--大資料架構篇 人工智慧-智慧創意平臺架構成長之路(三)--機器學習演算法工程服務化 人工智慧-智慧創意平臺架構成長之路(四)-豐富多彩的banner圖生成解密第一部分(對標阿里鹿班的設計)   (成長之

第一部分批處理的專用命令

分隔符 pause exe call pat sage 設置環境變量 定義 順序 批處理文件是將一系列命令按一定的順序集合為一個可執行的文本文件,其擴展名為BAT。這些命令統稱批處理命令,下面我就來給大家介紹一下批處理的命令。 1、 REM REM 是個註釋命令一般是用來給

jQuery源碼逐行分析學習02(第一部分jQuery的一些變量和函數)

篩選 復雜 我們 分解 support letter content 變量 new對象 第一次嘗試使用Office Word,方便程度大大超過網頁在線編輯,不過初次使用,一些內容不甚熟悉,望各位大神見諒~ 在上次的文章中,把整個jQuery的結構進行了梳理,得到了整個jQu

第一部分MongoDB備忘錄

taf slow 日誌 復制集 副本集 () nss nec ror 一、NoSQL 簡介   Nosql的全稱是Not Only Sql,這個概念早起就有人提出,在09年的時候比較火。Nosql指的是非關系型數據庫,而我們常用的都是關系型數據庫。就像我們常用的mysql,

Java入門第一資料型別

Java入門第一課:資料型別 文章目錄 Java入門第一課:資料型別 1. 科普類 2.資料型別 2.1整型 2.2浮點型別 2.3 char型別 2.4布林型別 2.5變數

什麼是REST——適合初學者的一種簡單解釋,第一部分介紹

  原文地址:https://medium.com/extend/what-is-rest-a-simple-explanation-for-beginners-part-1-introduction-b4a072f8740f     這篇文章是解釋REST基本概念的兩篇文章中的第一篇。      閱讀

數字影象處理的筆記(一)第一部分概念和應用領域

影象處理的部分先做一個大概的記錄,後續深入學習後展開。內容圍繞影象的分割和增強展開。 只是相關技術的某些應用,也可能不盡準確,為了記錄和學習。 第一部分:概念和應用領域 第二部分:相關的程式碼實現 ----------------------------針對畫素本身的操作,非

Python 語言學習 第一資料型別(數字,集合,布林型別,操作符)

Python語言最常用的物件是變數和常量,常量的值是字面意思,其值是不可變的,變數的值是可變的,例如,123,"上海"是常量,而a=1,a=2,其中a是變數名。內建的核心資料型別有:數字、字串、列表、字典、元組、檔案、集合、None和布林型別。Python是強型別的語言,變數的資料型別是由初始化的常量來指定的