Java基础之理解Annotation
2019獨角獸企業重金招聘Python工程師標準>>>
| 一、概念 Annontation是Java5開始引入的新特征。中文名稱一般叫注解。它提供了一種安全的類似注釋的機制,用來將任何的信息或元數據(metadata)與程序元素(類、方法、成員變量等)進行關聯。 更通俗的意思是為程序的元素(類、方法、成員變量)加上更直觀更明了的說明,這些說明信息是與程序的業務邏輯無關,并且是供指定的工具或框架使用的。 Annontation像一種修飾符一樣,應用于包、類型、構造方法、方法、成員變量、參數及本地變量的聲明語句中。 二、原理 Annotation其實是一種接口。通過Java的反射機制相關的API來訪問annotation信息。相關類(框架或工具中的類)根據這些信息來決定如何使用該程序元素或改變它們的行為。 annotation是不會影響程序代碼的執行,無論annotation怎么變化,代碼都始終如一地執行。 Java語言解釋器在工作時會忽略這些annotation,因此在JVM 中這些annotation是“不起作用”的,只能通過配套的工具才能對這些annontaion類型的信息進行訪問和處理。 Annotation與interface的異同: 1)、Annotation類型使用關鍵字@interface 而不是interface。 這個關鍵字聲明隱含了一個信息:它是繼承了java.lang.annotation.Annotation接口,并非聲明了一個interface 2)、Annotation類型、方法定義是獨特的、受限制的。 Annotation類型的方法必須聲明為無參數、無異常拋出的。這些方法定義了annotation的成員:方法名成為了成員名,而方法返回值成為了成員的類型。而方法返回值類型必須為primitive類型、Class類型、枚舉類型、annotation類型或者由前面類型之一作為元素的一維數組。方法的后面可以使用default和一個默認數值來聲明成員的默認值,null不能作為成員默認值,這與我們在非annotation類型中定義方法有很大不同。 Annotation類型和它的方法不能使用annotation類型的參數、成員不能是generic。只有返回值類型是Class的方法可以在annotation類型中使用generic,因為此方法能夠用類轉換將各種類型轉換為Class。 3)、Annotation類型又與接口有著近似之處。 它們可以定義常量、靜態成員類型(比如枚舉類型定義)。Annotation類型也可以如接口一般被實現或者繼承。 三、應用場合 annotation一般作為一種輔助途徑,應用在軟件框架或工具中,在這些工具類中根據不同的annontation注解信息采取不同的處理過程或改變相應程序元素(類、方法及成員變量等)的行為。 例如:Junit、Struts、Spring等流行工具框架中均廣泛使用了annontion。使代碼的靈活性大提高。 ?四、常見標準的Annotation 從java5版本開始,自帶了三種標準annontation類型, (1)、Override java.lang.Override是一個markerannotation類型,它被用作標注方法。它說明了被標注的方法重載了父類的方法,起到了斷言的作用。如果我們使用了這種annotation在一個沒有覆蓋父類方法的方法時,java編譯器將以一個編譯錯誤來警示。 這個annotaton常常在我們試圖覆蓋父類方法而確又寫錯了方法名時加一個保障性的校驗過程。 (2)、Deprecated Deprecated也是一種markerannotation。當一個類型或者類型成員使用@Deprecated修飾的話,編譯器將不鼓勵使用這個被標注的程序元素。所以使用這種修飾具有一定的“延續性”:如果我們在代碼中通過繼承或者覆蓋的方式使用了這個過時的類型或者成員,雖然繼承或者覆蓋后的類型或者成員并不是被聲明為@Deprecated,但編譯器仍然要報警。 注意:@Deprecated這個annotation類型和javadoc中的@deprecated這個tag是有區別的:前者是java編譯器識別的,而后者是被javadoc工具所識別用來生成文檔(包含程序成員為什么已經過時、它應當如何被禁止或者替代的描述)。 (3)、SuppressWarnings 此注解能告訴Java編譯器關閉對類、方法及成員變量的警告。 有時編譯時會提出一些警告,對于這些警告有的隱藏著Bug,有的是無法避免的,對于某些不想看到的警告信息,可以通過這個注解來屏蔽。 SuppressWarning不是一個markerannotation。它有一個類型為String[]的成員,這個成員的值為被禁止的警告名。對于javac編譯器來講,被-Xlint選項有效的警告名也同樣對@SuppressWarings有效,同時編譯器忽略掉無法識別的警告名。 annotation語法允許在annotation名后跟括號,括號中是使用逗號分割的name=value對用于為annotation的成員賦值: 代碼: @SuppressWarnings(value={"unchecked","fallthrough"})public? void?lintTrap() {? /* ?sloppy method body omitted? */?} 在這個例子中SuppressWarningsannotation類型只定義了一個單一的成員,所以只有一個簡單的value={...}作為name=value對。又由于成員值是一個數組,故使用大括號來聲明數組值。 注意:我們可以在下面的情況中縮寫annotation:當annotation只有單一成員,并成員命名為"value="。這時可以省去"value="。比如將上面的SuppressWarningsannotation進行縮寫: 代碼: @SuppressWarnings({"unchecked","fallthrough"})如果SuppressWarnings所聲明的被禁止警告個數為一個時,可以省去大括號: @SuppressWarnings("unchecked")五、自定義annontation示例 ? 示例共涉及四個類: 清單1:Author.java package?com.magc.annotation;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; /** * 定義作者信息,name和group *? @author ?magc * */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public?@ interface?Author { String name(); String group(); } 清單2:Description.java /***? */ package?com.magc.annotation; 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; /** *? @author ?magc * * 定義描述信息 value */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @Documented public?@ interface?Description { String value(); } 清單3:Utility.java package?com.magc.annotation;@Description(value?=?"這是一個有用的工具類") public? class?Utility { @Author(name?=?"haoran_202",group="com.magc") public?String work() { return?"work over!"; } } 注:這是個普通的Java類,運行了@Description和@Author注解。 清單3:AnalysisAnnotation.java package?com.magc.annotation;import?java.lang.reflect.Method; public? class?AnalysisAnnotation { /** * 在運行時分析處理annotation類型的信息 *? *? */ public? static? void?main(String[] args) { try?{ // 通過運行時反射API獲得annotation信息 Class rt_class?=?Class.forName("com.magc.annotation.Utility"); Method[] methods?=?rt_class.getMethods(); boolean?flag?=?rt_class.isAnnotationPresent(Description. class); if(flag) { Description description?=?(Description)rt_class.getAnnotation(Description. class); System.out.println("Utility's Description--->"+description.value()); for?(Method method : methods) { if(method.isAnnotationPresent(Author. class)) { Author author?=?(Author)method.getAnnotation(Author. class); System.out.println("Utility's Author--->"+author.name()+"?from?"+author.group()); } } } }? catch?(ClassNotFoundException e) { e.printStackTrace(); } } } |
轉載于:https://my.oschina.net/float2net/blog/95861
總結
以上是生活随笔為你收集整理的Java基础之理解Annotation的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ADempiere3.6.0LTS -
- 下一篇: quartz2d 实现太极图