Java進階(一)Annotation(註解)
原創文章,轉載請務必將下面這段話置於文章開頭處(保留超連結)。
本文轉發自,
Annotation是Java5開始引入的特性。它提供了一種安全的類似於註釋和Java doc的機制。實事上,Annotation已經被廣泛用於各種Java框架,如Spring,Jersey,JUnit,TestNG。註解相當於是一種嵌入在程式中的後設資料,可以使用註解解析工具或編譯器對其進行解析,也可以指定註解在編譯期或執行期有效。這些後設資料與程式業務邏輯無關,並且是供指定的工具或框架使用的。
元註解的作用就是負責註解其他註解。Java5定義了4個標準的Meta Annotation型別,它們被用來提供對其它 Annotation型別作說明。
@Target
說明了Annotation所修飾的物件範圍:Annotation可被用於 packages、types(類、介面、列舉、Annotation型別)、型別成員(方法、構造方法、成員變數、列舉值)、方法引數和本地變數(如迴圈變數、catch引數)。在Annotation型別的宣告中使用了@Target
可更加明晰其修飾的目標。
@Target
作用:用於描述註解的使用範圍,即被描述的註解可以用在什麼地方
@Target
取值(ElementType)
CONSTRUCTOR
:用於描述構造器FIELD
:用於描述域LOCAL_VARIABLE
:用於描述區域性變數METHOD
:用於描述方法PACKAGE
:用於描述包PARAMETER
:用於描述引數TYPE
:用於描述類、介面(包括註解型別) 或enum宣告
@Retention
定義了該Annotation的生命週期:某些Annotation僅出現在原始碼中,而被編譯器丟棄;而另一些卻被編譯在class檔案中;編譯在class檔案中的Annotation可能會被虛擬機器忽略,而另一些在class被裝載時將被讀取(請注意並不影響class的執行,因為Annotation與class在使用上是被分離的)。@Retention
有唯一的value作為成員。
@Retention
作用:表示需要在什麼級別儲存該註釋資訊,用於描述註解的生命週期(即:被描述的註解在什麼範圍內有效)
@Retention
取值來自java.lang.annotation.RetentionPolicy
的列舉型別值
SOURCE:在原始檔中有效(即原始檔保留)
CLASS:在class檔案中有效(即class保留)
RUNTIME:在執行時有效(即執行時保留)
@Documented
@Documented
用於描述其它型別的annotation應該被作為被標註的程式成員的公共API,因此可以被例如javadoc此類的工具文件化。@Documented
是一個標記註解,沒有成員。
@Inherited
是一個標記註解。如果一個使用了@Inherited
修飾的annotation型別被用於一個class,則這個Annotation將被用於該class的子類。
在實際專案中,經常會碰到下面這種場景,一個介面的實現類或者抽象類的子類很多,經常需要根據不同情況(比如根據配置檔案)例項化並使用不同的子類。典型的例子是結合工廠使用職責鏈模式。
此時,可以為每個實現類加上特定的Annotation,並在Annotation中給該類取一個識別符號,應用程式可透過該識別符號來判斷應該例項化哪個子類。
下面這個例子,定義了一個名為Component的Annotation,它包含一個名為identifier的成員變數。
package com.jasongj.annotation;import java.lang.annotation.Documented;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;import java.lang.annotation.ElementType;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Documented@Inheritedpublic @interface Component { String identifier () default "";} |
對於上文所說的實現類加上@Component
package com.jasongj;import com.jasongj.annotation.Component;@Component(identifier="upper")public class UpperCaseComponent { public String doWork(String input) { if(input != null) { return input.toUpperCase(); } else { return null; } }} |
應用程式中可以透過反射獲取UpperCaseComponent對應的identifier
package com.jasongj;import com.jasongj.annotation.Component;public class Client {public static void main(String[] args) {try {Class componentClass = Class.forName("com.jasongj.UpperCaseComponent");if(componentClass.isAnnotationPresent(Component.class)) {Component component = (Component)componentClass.getAnnotation(Component.class);String identifier = component.identifier();System.out.println(String.format("Identifier for "+ "com.jasongj.UpperCaseComponent is ' %s '", identifier));} else {System.out.println("com.jasongj.UpperCaseComponent is not annotated by" + " com.jasongj.annotation.Component");}} catch (ClassNotFoundException ex) { ex.printStackTrace();}}} |
結果如下
1 |
Identifier for com.jasongj.UpperCaseComponent is ' upper ' |
如果把@Component
的@Retention
設定為 RetentionPolicy.SOURCE
或者RetentionPolicy.CLASS
,則會得到如下結果,驗證了上文中對@Retention
的描述
1 |
com.jasongj.UpperCaseComponent is not annotated by com.jasongj.annotation.Component |
Annotation的語法比較簡單,除了@符號的使用外,他基本與Java固有的語法一致,JavaSE中內建三個標準Annotation,定義在java.lang
中:
@Override
是一個標記型Annotation,說明了被標註的方法覆蓋了父類的方法,起到了斷言的作用。如果給一個非覆蓋父類方法的方法新增該Annotation,編譯器將報編譯錯誤。它有兩個典型的使用場景,一是在試圖覆蓋父類方法卻寫錯了方法名時報錯,二是刪除已被子類覆蓋(且用Annotation修飾)的父類方法時報錯。@Deprecated
標記型Annotation,說明被修改的元素已被廢棄並不推薦使用,編譯器會在該元素上加一條橫線以作提示。該修飾具有一定的“傳遞性”:如果我們透過繼承的方式使用了這個棄用的元素,即使繼承後的元素(類,成員或者方法)並未被標記為@Deprecated
,編譯器仍然會給出提示。@SuppressWarnnings
用於通知Java編譯器關閉對特定類、方法、成員變數、變數初始化的警告。此種警告一般代表了可能的程式錯誤,例如當我們使用一個generic collection類而未提供它的型別時,編譯器將提示“unchecked warning”的警告。通常當這種情況發生時,我們需要查詢引起警告的程式碼,如果它真的表示錯誤,我們就需要糾正它。然而,有時我們無法避免這種警告,例如,我們使用必須和非generic的舊程式碼互動的generic collection類時,我們無法避免這個unchecked warning,此時可以在呼叫的方法前增加@SuppressWarnnings
通知編譯器關閉對此方法的警告。
@SuppressWarnnings
不是標記型Annotation,它有一個型別為String[]的成員,這個成員的值為被禁止的警告名。常見的警告名為下。
unchecked
執行了未檢查的轉換時的警告。例如當使用集合時沒有用泛型來指定集合的型別finally
finally子句不能正常完成時的警告fallthrough
當switch程式塊直接通往下一種情況而沒有break時的警告deprecation
使用了棄用的類或者方法時的警告seriel
在可序列化的類上缺少serialVersionUID時的警告path
在類路徑、原始檔路徑等中有不存在的路徑時的警告all
對以上所有情況的警告
Annotation型別使用關鍵字
@interface
而非interface
。注意開頭的@
符號Annotataion的方法定義是受限制的。其方法必須宣告為無引數、無異常丟擲的。這些方法同時也定義了Annotation的成員——方法名即為成員名,而方法返回型別即為成員型別。方法返回型別必須為Java基礎型別、Class型別、列舉型別、Annotation型別或者相應的一維陣列。方法後面可以使用default關鍵字和一個預設數值來宣告成員的預設值,null不能作為成員預設值。成員一般不能是泛型,只有當其型別是Class時可以使用泛型,因為此方法能夠用型別轉換將各種型別轉換為Class
Annotation和interface都可以定義常量、靜態成員型別,也都可以被實現或者繼承
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/964/viewspace-2814031/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Java —— 註解(Annotation)Java
- Java Annotation 註解Java
- Java 註解(Annotation)Java
- java-Annotation註解Java
- Java之註解(Annotation)Java
- Java 註解Annotation研究Java
- Java註解(Annotation)詳解Java
- 【Java.Core】註解 - AnnotationJava
- Java註解(Annotation):請不要小看我!Java
- Java 註解 (Annotation)淺入深出Java
- java進階之自定義註解Java
- 元註解——java.lang.annotation.Target(1.8)Java
- 關於Java註解(annotation)的簡單理解Java
- Java學習之註解Annotation實現原理Java
- JAVA ANNOTATION詳解Java
- Spring(三)——註解方式(Annotation)Spring
- 【framework】spring-註解(annotation)FrameworkSpring
- Android 註解系列之Annotation(二)Android
- 高階工程師-Java註解工程師Java
- java annotationJava
- Java高階特性-註解:註解實現Excel匯出功能JavaExcel
- Java高階特性——註解,簡單易懂Java
- 註解專題(一)Java元註解,內建註解Java
- 【進階】Spring中的註解與反射Spring反射
- 深入理解 Java 註解 [元註解(一)]Java
- Android進階——Java註解實戰之APT構建模組化的第一步AndroidJavaAPT
- Java建立AnnotationJava
- java 的annotationJava
- Spring進階案例之註解和IoC案例Spring
- Java自定義Annotation,通過反射解析AnnotationJava反射
- java反射——反射AnnotationJava反射
- Java進階—JDK SPI原始碼詳解JavaJDK原始碼
- hibernate annotation註解方式來處理對映關係
- Java進階之路Java
- 基於AOP的MVP框架(三)GoMVP進階註解MVP框架Go
- 基於AOP的MVP框架(二)GoMVP進階註解MVP框架Go
- SpringBoot快速整合Mybatis(去XML化+註解進階)Spring BootMyBatisXML
- java註解Java