一、概念html
Annontation是Java5開始引入的新特徵。中文名稱通常叫註解。它提供了一種安全的相似註釋的機制,用來將任何的信息或元數據(metadata)與程序元素(類、方法、成員變量等)進行關聯。java
更通俗的意思是爲程序的元素(類、方法、成員變量)加上更直觀更明瞭的說明,這些說明信息是與程序的業務邏輯無關,而且是供指定的工具或框架使用的。android
Annontation像一種修飾符同樣,應用於包、類型、構造方法、方法、成員變量、參數及本地變量的聲明語句中。web
二、原理數組
Annotation實際上是一種接口。經過Java的反射機制相關的API來訪問annotation信息。相關類(框架或工具中的類)根據這些信息來決定如何使用該程序元素或改變它們的行爲。安全
annotation是不會影響程序代碼的執行,不管annotation怎麼變化,代碼都始終如一地執行。框架
Java語言解釋器在工做時會忽略這些annotation,所以在JVM 中這些annotation是「不起做用」的,只能經過配套的工具才能對這些annontaion類型的信息進行訪問和處理。ide
Annotation與interface的異同:工具
1)、Annotation類型使用關鍵字@interface而不是interface。spa
這個關鍵字聲明隱含了一個信息:它是繼承了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 是一個marker annotation類型,它被用做標註方法。它說明了被標註的方法重載了父類的方法,起到了斷言的做用。若是咱們使用了這種annotation在一個沒有覆蓋父類方法的方法時,java編譯器將以一個編譯錯誤來警示。
這個annotaton經常在咱們試圖覆蓋父類方法而確又寫錯了方法名時加一個保障性的校驗過程。
(2)、Deprecated
Deprecated也是一種marker annotation。當一個類型或者類型成員使用@Deprecated修飾的話,編譯器將不鼓勵使用這個被標註的程序元素。因此使用這種修飾具備必定的 「延續性」:若是咱們在代碼中經過繼承或者覆蓋的方式使用了這個過期的類型或者成員,雖然繼承或者覆蓋後的類型或者成員並非被聲明爲 @Deprecated,但編譯器仍然要報警。
注意:@Deprecated這個annotation類型和javadoc中的 @deprecated這個tag是有區別的:前者是java編譯器識別的,然後者是被javadoc工具所識別用來生成文檔(包含程序成員爲何已通過時、它應當如何被禁止或者替代的描述)。
(3)、SuppressWarnings
此註解能告訴Java編譯器關閉對類、方法及成員變量的警告。
有時編譯時會提出一些警告,對於這些警告有的隱藏着Bug,有的是沒法避免的,對於某些不想看到的警告信息,能夠經過這個註解來屏蔽。
SuppressWarning不是一個marker annotation。它有一個類型爲String[]的成員,這個成員的值爲被禁止的警告名。對於javac編譯器來說,被-Xlint選項有效的警告名也一樣對@SuppressWarings有效,同時編譯器忽略掉沒法識別的警告名。
annotation語法容許在annotation名後跟括號,括號中是使用逗號分割的name=value對用於爲annotation的成員賦值:
代碼:
@SuppressWarnings(value={"unchecked","fallthrough"})
publicvoid lintTrap() { /* sloppy method body omitted */ }
在這個例子中SuppressWarnings annotation類型只定義了一個單一的成員,因此只有一個簡單的value={...}做爲name=value對。又因爲成員值是一個數組,故使用大括號來聲明數組值。
注意:咱們能夠在下面的狀況中縮寫annotation:當annotation只有單一成員,併成員命名爲"value="。這時能夠省去"value="。好比將上面的SuppressWarnings annotation進行縮寫:
代碼:
@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 ="這是一個有用的工具類")
publicclass 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;
publicclass AnalysisAnnotation {
/**
* 在運行時分析處理annotation類型的信息
*
*
*/
publicstaticvoid 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();
}
}
}
注:這是個與自定義@Description和@Author配套的基礎框架或工具類,經過此類來得到與普通Java類Utility.java關聯的信息,即描述和做者。
運行AnalysisAnnotation,輸出結果爲:
Utility's Description--->這是一個有用的工具類
Utility's Author--->haoran_202 from com.magc
轉自:http://www.cnblogs.com/mandroid/archive/2011/07/18/2109829.html