轉載自:http://william750214.javaeye.com/blog/298104java
元數據的做用編程
若是要對於元數據的做用進行分類,目前尚未明確的定義,不過咱們能夠根據它所起的做用,大體可分爲三類:安全
l 編寫文檔:經過代碼裏標識的元數據生成文檔。併發
l 代碼分析:經過代碼裏標識的元數據對代碼進行分析。ide
l 編譯檢查:經過代碼裏標識的元數據讓編譯器能實現基本的編譯檢查。函數
基本內置註釋工具
@Override註釋能實現編譯時檢查,你能夠爲你的方法添加該註釋,以聲明該方法是用於覆蓋父類中的方法。若是該方法不是覆蓋父類的方法,將會在編譯時報錯。例如咱們爲某類重寫toString()方法卻寫成了tostring(),而且咱們爲該方法添加了@Override註釋;this
@Deprecated的做用是對不該該在使用的方法添加註釋,當編程人員使用這些方法時,將會在編譯時顯示提示信息,它與javadoc裏的@deprecated標記有相同的功能,準確的說,它還不如javadoc @deprecated,由於它不支持參數,線程
注意:要了解詳細信息,請使用 -Xlint:deprecation 從新編譯。對象
@SuppressWarnings與前兩個註釋有所不一樣,你須要添加一個參數才能正確使用,這些參數值都是已經定義好了的,咱們選擇性的使用就行了,參數以下:
deprecation 使用了過期的類或方法時的警告
unchecked 執行了未檢查的轉換時的警告,例如當使用集合時沒有用泛型 (Generics) 來指定集合保存的類型
fallthrough 當 Switch 程序塊直接通往下一種狀況而沒有 Break 時的警告
path 在類路徑、源文件路徑等中有不存在的路徑時的警告
serial 當在可序列化的類上缺乏 serialVersionUID 定義時的警告
finally 任何 finally 子句不能正常完成時的警告
all 關於以上全部狀況的警告
注意:要了解詳細信息,請使用 -Xlint:unchecked 從新編譯。
定製註釋類型
好的,讓咱們建立一個本身的註釋類型(annotation type)吧。它相似於新建立一個接口類文件,但爲了區分,咱們須要將它聲明爲@interface,以下例:
public @interface NewAnnotation {
}
使用定製的註釋類型
咱們已經成功地建立好一個註釋類型NewAnnotation,如今讓咱們來嘗試使用它吧,若是你還記得本文的第一部分,那你應該知道他是一個標記註釋,使用也很容易,以下例:
public class AnnotationTest {
@NewAnnotation
public static void main(String[] args) {
}
}
添加變量
J2SE 5.0裏,咱們瞭解到內置註釋@SuppressWarnings()是可使用參數的,那麼自定義註釋能不能定義參數個數和類型呢?答案是固然能夠,但參數類型只容許爲基本類型、String、Class、枚舉類型等,而且參數不能爲空。咱們來擴展NewAnnotation,爲之添加一個String類型的參數,示例代碼以下:
public @interface NewAnnotation {
String value();
}
使用該註釋的代碼以下:正如你所看到的,該註釋的使用有兩種寫法,這也是在以前的文章裏所提到過的。若是你忘了這是怎麼回事,那就再去翻翻吧。
public class AnnotationTest {
@NewAnnotation("Just a Test.")
public static void main(String[] args) {
sayHello();
}
@NewAnnotation(value="Hello NUMEN.")
public static void sayHello() {
// do something
}
}
爲變量賦默認值
咱們對Java自定義註釋的瞭解正在不斷的增多,不過咱們還須要更過,在該條目裏咱們將瞭解到如何爲變量設置默認值,咱們再對NewAnnotaion進行修改,看看它會變成什麼樣子,不只參數多了幾個,連類名也變了。但仍是很容易理解的,咱們先定義一個枚舉類型,而後將參數設置爲該枚舉類型,並賦予默認值。
public @interface Greeting {
public enum FontColor {RED, GREEN, BLUE};
String name();
String content();
FontColor fontColor() default FontColor.BLUE;
}
限定註釋使用範圍
當咱們的自定義註釋不斷的增多也比較複雜時,就會致使有些開發人員使用錯誤,主要表如今不應使用該註釋的地方使用。爲此,Java提供了一個ElementType枚舉類型來控制每一個註釋的使用範圍,好比說某些註釋只能用於普通方法,而不能用於構造函數等。下面是Java定義的ElementType枚舉:
package java.lang.annotation;
public enum ElementType {
TYPE, // Class, interface, or enum (but not annotation)
FIELD, // Field (including enumerated values)
METHOD, // Method (does not include constructors)
PARAMETER, // Method parameter
CONSTRUCTOR, // Constructor
LOCAL_VARIABLE, // Local variable or catch clause
ANNOTATION_TYPE, // Annotation Types (meta-annotations)
PACKAGE // Java package
}
下面咱們來修改Greeting註釋,爲之添加限定範圍的語句,這裏咱們稱它爲目標(Target)使用方法也很簡單,以下:
@Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })
public @interface Greeting {
}
正如上面代碼所展現的,咱們只容許Greeting註釋標註在普通方法和構造函數上,使用在包申明、類名等時,會提示錯誤信息。
註釋保持性策略
public enum RetentionPolicy {
SOURCE,// Annotation is discarded by the compiler
CLASS,// Annotation is stored in the class file, but ignored by the VM
RUNTIME// Annotation is stored in the class file and read by the VM
}
RetentionPolicy的使用方法與ElementType相似,簡單代碼示例以下:
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })
文檔化功能
Java提供的Documented元註釋跟Javadoc的做用是差很少的,其實它存在的好處是開發人員能夠定製Javadoc不支持的文檔屬性,並在開發中應用。它的使用跟前兩個也是同樣的,簡單代碼示例以下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })
public @interface Greeting {
}
值得你們注意的是,若是你要使用@Documented元註釋,你就得爲該註釋設置RetentionPolicy.RUNTIME保持性策略。爲何這樣作,應該比較容易理解,這裏就不提了。
標註繼承
繼承應該是Java提供的最複雜的一個元註釋了,它的做用是控制註釋是否會影響到子類,簡單代碼示例以下:
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target( { ElementType.METHOD, ElementType.CONSTRUCTOR })
public @interface Greeting {
}
讀取註釋信息
當咱們想讀取某個註釋信息時,咱們是在運行時經過反射來實現的,若是你對元註釋還有點印象,那你應該記得咱們須要將保持性策略設置爲RUNTIME,也就是說只有註釋標記了@Retention(RetentionPolicy.RUNTIME)的,咱們才能經過反射來得到相關信息,下面的例子咱們將沿用前面幾篇文章中出現的代碼,並實現讀取AnnotationTest類全部方法標記的註釋並打印到控制檯。好了,咱們來看看是如何實現的吧:
public class AnnotationIntro {
public static void main(String[] args) throws Exception {
Method[] methods = Class.forName(
"com.gelc.annotation.demo.customize.AnnotationTest")
.getDeclaredMethods();
Annotation[] annotations;
for (Method method : methods) {
annotations = method.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(method.getName() + " : "
+ annotation.annotationType().getName());
}
Java併發編程中,用到了一些專門爲併發編程準備的 Annotation。 主要包括三類: 一、類 Annotation(註解) 就像名字同樣,這些註解是針對類的。主有要如下三個: @Immutable @ThreadSafe @NotThreadSafe
@ThreadSafe 是表示這個類是線程安全的。具體是否真安全,那要看實現者怎麼實現的了,反正打上這個標籤只是表示一下。不線程安全的類打上這個註解也沒事兒。 @Immutable 表示,類是不可變的,包含了 @ThreadSafe 的意思。 @NotThreadSafe 表示這個類不是線程安全的。若是是線程安全的非要打上這個註解,那也不會報錯。
這三個註解,對用戶和維護者是有益的,用戶能夠當即看出來這個類是不是線程安全的,維護者則是能夠根據這個註解,重點檢查線程安全方面。另外,代碼分析工具可能會利用這個註解。
二、域 Annotation(註解) 域註解是對類裏面成員變量加的註解。 三、方法 Annotation(註解) 方法註解是對類裏面方法加的註解。
域註解和方法註解都是用@GuardedBy( lock )來標識。裏面的Lock是告訴維護者:這個狀態變量,這個方法被哪一個鎖保護着。這樣能夠強烈的提示類的維護者注意這裏。
@GuardedBy( lock )有如下幾種使用形式:
一、@GuardedBy( "this" ) 受對象內部鎖保護 二、@GuardedBy( "fieldName" ) 受 與fieldName引用相關聯的鎖 保護。 三、@GuardedBy( "ClassName.fieldName" ) 受 一個類的靜態field的鎖 保存。 四、@GuardedBy( "methodName()" ) 鎖對象是 methodName() 方法的返值,受這個鎖保護。 五、@GuardedBy( "ClassName.class" ) 受 ClassName類的直接鎖對象保護。而不是這個類的某個實例的鎖對象。