Java注釋:探究和解釋

Java 5 SE的許多出色功能之一是Annotations構造的引入。
注釋是一些標簽,我們可以將其插入程序源代碼中,以使用某種工具對其進行處理并使其變得有意義。 注釋處理工具通常使用(Java 5 SE的)Reflection API在Java代碼或字節碼級別的源代碼級別處理代碼,以處理編譯器已將注釋放入其中的類文件。 Java注釋在網絡上的許多地方都得到了很好的解釋,但唯一能找到一個明智而完整的示例的地方是Prentice Hall出版的一本精裝書,名為Core Java:Volume II – Advanced Features,由Cay S. Horstmann撰寫。和加里·康奈爾。

網絡上幾乎所有試圖解釋注釋的地方都缺少為我們展示用于自定義書面注釋的注釋處理工具(APT)以及從代碼中使用注釋的最關鍵部分。 我已使用本書中的信息構建了一些注釋,用于驗證變量并從項目的屬性文件中初始化變量中的值。 我對www上缺少編寫自定義Java注釋的示例的觀察,促使我寫這篇文章。 因此,向您提供一個示例自定義Java注釋,以幫助您為自己可能要做的事情編寫自己的注釋。

我將帶您遍歷NullValueValidate批注,其名稱所暗示的目的是驗證其注釋的變量包含非null值。 如果在處理時發現null值,則將拋出NullPointerException

聲明注釋

讓我們首先聲明我們的注釋。 該聲明將由打算使用注釋來注釋其對象中變量的代碼使用。

package annotation.declaration;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;/*** Null Value Validate is, as the name suggests an annotation to* validate whether the parameter is null or not* @author         Y.Kamesh Rao**/
@Documented
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)public @interface NullValueValidate {String paramName();
}

注意“ interface”關鍵字前面的“ @”(AT)符號。 這是用于聲明注釋的語法。 這稱為注釋接口 。 界面的方法對應于注釋的元素。 paramName() –這是我們的注釋聲明包含的唯一元素。 它存儲帶注釋的字段的名稱,以便在處理時在消息中顯示它。 請注意,該聲明看起來像一個函數聲明。 其實就是這樣。 @interface實際上聲明了一個Java接口,該接口的實現由使用注釋的對象提供。 注釋處理器接收使用/實現注釋的對象,并調用注釋接口方法以檢索注釋元素。 在我們的例子中, NullValueValidateAnnotationProcessor將接收該類的對象,該類的某些字段使用NullValueValidate注釋進行了注釋。 然后,該處理器將調用paramName()方法來檢索此注釋元素的值。

我們使用3種Java提供的注釋來注釋聲明的屬性。 這些也可以稱為“ 內置注釋” ,用于“注釋” 。 (嗯,繞口令比這強得多)。 @Documented –表示在使用JavaDocs為此項目創建文檔時,必須包含注釋聲明。 缺省情況下,注釋是從使用javadocs命令生成的文檔中排除的。 @Target –指示您的Java程序中應對其應用注釋的目標元素。 它可以是字段,方法,類或整個包本身。 我們的NullValueValidate注釋僅適用于類字段。 這是此枚舉可能取的值–

  • TYPE –僅適用于Type。 類型可以是Java類或接口,也可以是Enum甚至是Annotation。
  • FIELD –僅適用于Java字段(在類級別聲明的對象,實例或靜態)。
  • 方法–僅適用于方法。
  • 參數–僅應用于方法定義中的方法參數。
  • 構造函數–僅適用于類的構造函數。
  • LOCAL_VARIABLE –僅適用于局部變量。 (在方法或代碼塊中聲明的變量)。
  • ANNOTATION_TYPE –僅適用于注釋類型。
  • 包裝-僅適用于包裝。

@Retention –指示用于注釋的保留策略。 簡單來說,我們將保留注釋很長時間。 有三個可能的值–

  • 源–注釋將被編譯器丟棄。
  • CLASS –注釋由編譯器記錄在類文件中,但VM在運行時無需保留。 這是默認行為。
  • RUNTIME –注釋由編譯器記錄在類文件中,并在運行時由VM保留,因此可以通過反射方式讀取它們。

由于我們計劃在程序運行時處理批注,因此將RetentionPolicy設置為RUNTIME@Target@Retention也稱為元注釋。

注釋處理工具

注釋處理器工具,解析它接收的對象,并在仔細檢查對象中找到正在處理的注釋時采取編程的措施。 這是我們先前聲明的注釋的注釋處理器– NullValueValidate

package annotation.processor;import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import annotation.declaration.NullValueValidate;/*** The class file to actually carry out the validations* for the various validate annotations we have declared* @author         Y.Kamesh Rao*/
public class NullValueValidateAnnotationProcessor {/*** Method to process all the annotations* @param obj    The name of the object where*               annotations are to be identified and*               processed*/public static void processAnnotations(Object obj) {try {Class cl = obj.getClass();// Checking all the fields for annotationsfor(Field f : cl.getDeclaredFields()) {// Since we are Validating fields, there may be many// NullPointer and similar exceptions thrown,// so we need  to catch themtry {// Processing all the annotations on a single fieldfor(Annotation a : f.getAnnotations()) {// Checking for a NullValueValidate annotationif(a.annotationType() == NullValueValidate.class) {NullValueValidate nullVal = (NullValueValidate) a;System.out.println('Processing the field : '+ nullVal.paramName());// Setting the field to be accessible from our class// is it is a private member of the class under processing// (which its most likely going to be)// The setAccessible method will not work if you have// Java SecurityManager configured and active.f.setAccessible(true);// Checking the field for a null value and// throwing an exception is a null value encountered.// The get(Object obj) method on Field class returns the// value of the Field for the Object which is under test right now.// In other words, we need to send 'obj' as the object// to this method since we are currently processing the// annotations present on the 'obj' Object.if(f.get(obj) == null) {throw new NullPointerException('The value of the field '+f.toString()+' can't be NULL.');} elseSystem.out.println('Value of the Object : '+f.get(obj));}}} catch(Exception e) {System.out.println(e.getMessage());e.printStackTrace();}}} catch(Exception e) {System.out.println(e.getMessage());e.printStackTrace();}}
}

大部分代碼是帶有注釋的自我解釋。 請參考該代碼以了解詳細信息。 基本上,它具有一個稱為processAnnotations的靜態方法,該方法采用包含需要處理的注釋的類的對象。 然后,我們使用Java Reflection API處理此接收到的對象參數中的每個Field,并在字段上找到NullValueValidate注釋時采取必要的空值驗證操作。 如果找到空值,則拋出NullPointerException或在控制臺上打印該值。

注釋用法請參考以下代碼,該代碼使用我們剛剛實現的NullValueValidate注釋。 它也使用NullValueValidateAnnotationProcessor在運行時通過從其構造函數調用它在其字段上處理聲明的注釋。 還要注意,注釋的使用方式與變量或字段聲明的訪問修飾符(如private或public)相似。 通常,輸入換行符可以提高代碼的可讀性。 否則,注釋可以很好地與變量/字段聲明在同一行中。 注釋的名稱前面帶有“ @”(AT)符號。

package annotation;import annotation.declaration.NullValueValidate;
import annotation.processor.NullValueValidateAnnotationProcessor;/** Main class to test the Annotations  *   @author         Y.Kamesh Rao */
public class AnnotationExample {@NullValueValidate(paramName = 'testVar1') private String testVar1;@NullValueValidate(paramName = 'testVar2') private String testVar2;public AnnotationExample() {testVar2 = 'Testing the Null Value Validation...It Works...!';         // Calling the processor to process the annotations applied         // on this class object.         NullValueValidateAnnotationProcessor.processAnnotations(this);     }     public static void main(String args[]) {AnnotationExample ae = new AnnotationExample();     }
}

輸出量

Processing the field:testVar1 
Value of the Object:Testing the Null Value Validation...It Works...!
Processing the field:testVar2 
The value of the field private java.lang.String annotation.AnnotationExample.testVar2 cannot be NULL.
java.lang.NullPointerException:The value of the field private java.lang.String annotation.AnnotationExample.testVar2 cannot be NULL.at annotation.processor.NullValueValidateAnnotationProcessor.processAnnotation
(NullValueValidateAnnotationProcessor.java:66)at annotation.AnnotationExample.(AnnotationExample.java:28)at annotation.AnnotationExample.main(AnnotationExample.java:33)

結論

我做這個示例注釋程序很有趣,現在我實現了許多自定義注釋,以從屬性文件中加載屬性,驗證數據庫字段長度等。注釋極大地減少了代碼的冗長性,因此使其更加簡單易讀。 注釋可用于日志記錄,生成依賴于代碼的部署描述符以及其他機械和重復的作業。 我為你們編寫這篇文章帶來了很多樂趣。 希望您能從中受益。

參考: Java注釋:我們的JCG合作伙伴 Y Kamesh Rao在OrangeApple博客上進行了探索和解釋 。


翻譯自: https://www.javacodegeeks.com/2012/08/java-annotations-explored-explained.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/371456.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/371456.shtml
英文地址,請注明出處:http://en.pswp.cn/news/371456.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C# 類

一 string 類型 變量.Length - 字符串長度,返回int類型 string s "abcdefg"; int a s . Length; Console.WriteLine(a); // 輸出結果為:7(此字符串有7個字符) // Length返回有多少個字符&am…

node+mongodb+win7

一、安裝mongodb,參照教程,注意要先啟動mongod.exe,再啟動mongd.exe。 轉載于:https://www.cnblogs.com/iloveyou-sky/p/7396997.html

cdrom是多媒體微型計算機,全國計算機二級題庫第三章

同時按下CTRLALTDEL組合鍵的作用是(使用任務管理器關閉不響應的應用程序下列說法正確的是(在微型機性能指標中,CPU的主頻越離,其運算速度越快)微型計算機鍵盤上的Tab鍵是(交替換檔鍵)微型計算機鍵盤上的Enter鍵是(回車鍵)微型計算機的運行速度的單位是mi…

Spring MVC控制器JUnit測試

JUnit測試Spring MVC控制器并非易事 。 但是最近,一個新項目 (即將在Spring推出)提供了新工具來簡化此工作。 這篇文章說明了如何通過JUnit測試來測試一個簡單的控制器。 該代碼是JUnit Testing Spring Service和DAO(帶有內存數據…

java基礎03變量和基本數據類型

package cn.bdqn.test;/*** * author 小豆腐* * 變量:會變化的量??* 一個數據在內存中存儲空間的表示!在運行期間可以動態改變!* * 關鍵字:在java中已經被使用或者定義的單詞!不能作為變量名&#xff01…

5.set集合

list_1 [1,2,3,4,5]list_2 [1,3,5,7,9]#列表轉成set集合set_1 set(list_1)set_2 set(list_2)#交集print(set_1.intersection(set_2))print(set_1 & set_2)#判斷沒有交集print(set(["a","b"]).isdisjoint(set_1))#并集print(set_1.union(set_2))pri…

JavaFX中基于表達式的PathTransitions

在JavaFX中,您可以使用PathTransition對象為路徑上的節點設置動畫。 PathTransitions使用Shape對象描述它們需要沿其動畫的路徑。 JavaFX提供了各種類型的形狀(例如,多邊形,圓形,多邊形,路徑)。…

html 顯示視頻列表,dvd光碟制作節目軌菜單布局,不要視頻縮略圖,只顯示文件列表...

“如何在刻錄視頻光盤時自定義制作菜單?實現的效果就是當光盤插入DVD影碟機播放時,首先會出現一個所有視頻文件列表的菜單(節目軌菜單),就相似于音樂CD曲目表一樣,不需要有視頻縮略圖,可通過遙控器選擇性播放列表中某一…

v3學院教你學習-task和function的異同

v3學院教你學習-task和function的異同 task(任務)與function(函數)的不同 任務與函數主要有以下四點不同: l 函數只能與主模塊共用一個仿真時間單位,而任務定義自己的仿真時間單位。 l 函數不能啟動任務&am…

Spring事件的觀察者模式

介紹 觀察者模式的本質是“定義對象之間的一對多依賴關系,以便當一個對象改變狀態時,其所有依賴關系都會得到通知并自動更新。” GoF。 觀察者模式是發布/訂閱模式的子集,它允許許多觀察者對象查看事件。 可以在不同的情況下使用此模式&#…

jQuery選擇什么版本 1.x? 2.x? 3.x?

目前jQuery有三個大版本: 1.x:兼容ie678,使用最為廣泛的,官方只做BUG維護,功能不再新增。因此一般項目來說,使用1.x版本就可以了,最終版本:1.12.4 (2016年5月20日)2.x:不兼容ie678&a…

Delta DVP 系列 PLC 各裝置 Modbus 地址

此Modbus地址表以 1 為基礎地址 Device Range Type DVP address (Hex) Modbus address (Dec) Effective ES/EX/SS SA/SX/SC EH S 000~255 bit 0000~00FF 000001~000256 0~127 0~1024 0~1024 S 256~511 bit 0100~01FF 000247~000512 S 512~767 bit 020…

Reporting Service 2008 “報表服務器數據庫內出錯。此錯誤可能是因連接失敗、超時或數據庫中磁盤空間不足而導致的”...

今天遇到了兩個關于Reporting Service的問題, 出現問題的環境為Microsoft SQL Server 2008 R2 (SP2) - 10.50.4000.0 (X64) 。具體情況請見下面描述。 1:在修改報表的訂閱后,保存時出現下面錯誤: 提示:報表服務器數據庫…

Java 7:HashMap與ConcurrentHashMap

從我過去有關性能的文章和HashMap案例研究中可能已經看到,Java線程安全性問題可以很輕松地使Java EE應用程序和Java EE容器崩潰。 在對Java EE性能問題進行故障排除時,我觀察到的最常見問題之一是由非線程安全的HashMap get()和pu…

計算機網絡按信息傳輸介質的性能來劃分,大學計算機基礎練習題網絡技術.doc...

網絡技術一、單選:1. 在計算機網絡中,表征數據傳輸可靠性的指標是( )。A?誤碼率 B?頻帶利用率C?信道容量 D?傳輸速率參考答案:A2. 和通信網絡相比,計算機網絡最本質的功能是( )。A?數據通信 B?資源共享C?提高計算機的可靠性…

【2017-03-02】集合、結構體、枚舉

集合和數組的差別: 數組:同一類型,固定長度集合:不同類型,不固定長度 一、普通集合(弱類型) 1、ArryList 使用集合首先要引用命名空間。 或者在ArryList上右鍵找“解析”。 2、集合的定義&#…

Hibernate懶/急加載示例

這篇文章將重點討論為什么以及如何在應用程序中使用稱為LAZY和EAGER加載的概念,以及如何使用Spring的休眠模板以EAGER方式加載LAZY實體。 當然,正如標題本身所暗示的那樣,我們將通過一個示例來說明這一點。 場景就是這樣; 您是一…

讀者使用計算機終端是指,全國2010年10月自學考試管理系統中計算機應用真題及答案...

A.上級模塊向下級模塊傳遞控制信號B.下級模塊對上級模塊傳遞控制信號C.同級模塊之間傳遞數據或控制信號D.上級模塊向下級模塊傳遞數據信號18.“客戶”數據表結構為:客戶編號、手機號、購物金額,合理的字段類型為( )A.字符型,字符型&#xff0…

軟件測試HW02-------fault error failure

程序一 問題一:i應該>0; 問題二: x為空 問題三:test x[2, 3, 5]; y 3;問題四:test: x[2]; y 3;程序二問題一:循環應該反過來;問題二:無;問題三:test:x[1];問題四:test: x[1,2,3…

Mathematica圖片局部變色

這篇博客來源于Stack-Exchange上的一個帖子,問題描述如下:如何將圖中的紅球變為藍球? 這個問題下面有很多答案,我選了最好的一個答案,代碼如下 img Import["C:/Users/1/Desktop/red.jpg"]; getReds[x_Image…