1. 程式人生 > >JavaSE第七十講:Retention及RetentionPolicy詳解

JavaSE第七十講:Retention及RetentionPolicy詳解

1. 繼續上一講內容,上一講的內容講到自定義註解

package com.ahuier.annotation;

public @interface AnnotationTest {
	
	//注意不要忘記小括號	
	//這邊給他定義註解資訊為預設值,則在AnnotationTest中註解時候,@AnnotationTest()引數預設為hello,如果有設值就按設定的值註解
	String value() default "hello";
	EnumTest value2(); //列舉也可以做為註解的值
}

enum EnumTest{
	Hello, World, Welcome;
}
package com.ahuier.annotation;

/*
 * @AnnotationTest(value = "hello") 與 @AnnotationTest("hello")都可以,前提是定義的註解裡面必須是 value 值
 */
@AnnotationTest(value2 = EnumTest.Welcome) 
public class AnnotationUsage {
	
	@AnnotationTest(value = "hello", value2 = EnumTest.World)
	public void method(){
		System.out.println("usage of annotation");
	}
	public static void main(String[] args) {
		AnnotationUsage usage = new AnnotationUsage();
		usage.method();
	}
}

【說明】:Single-value annotiong: value成員設定預設值,用"default"關鍵詞。當然註解也可以用陣列形式來設定值。

2. 學習完以上兩個程式之後,這兩個程式是基於上一講自定義註解內容所講的,現在我們要做一些實際的註解的例子。

自定義Annotation型別,使用@interface自行定義Annotation型態時候,實際上是自動繼承了java.lang.annotation.Annotation介面,由編譯程式自動為您完成其它產生的細節,在定義Annotation型態,不能繼承其它的Annotation態或是介面

檢視JDK Doc文件的Annotation介面

java.lang.annotation
Interface Annotation
public interface Annotation
    The common interface extended by all annotation types. Note that an interface that manually extends this one does not define an annotation type. Also note that this interface does not itself define an annotation type.

[它是一個被annotation型別所繼承的公共的介面.

注意一個介面手動的去繼承這個介面並不是定義了註解型別。再注意這個介面本身並沒有定義註解型別]

當我們使用 @interface 關鍵字定義一個註解時,該註解隱含地繼承了 java.lang.annotation.Annotation 介面;如果我們定義了一個介面,並且讓該介面繼承自 Annotation,那麼我們所定義的介面依然還是介面而不是註解;Annotation 本身是介面型別而不是註解型別。可以與 Enum 類比。

3. 定義Annotation型態時也可以使用包來管理類別,方法類同於類的匯入功能

4. 告知編譯程式如何處理@Retention  [Retention: 保持,保留]

1) java.lang.annotation.Retention型態可以在您定義Annotation型態時,指示編譯程式該如何對待您的自定義的Annotation型態

預設情況下編譯程式會將Annotation資訊留在.class檔案中,但不被虛擬機器讀取,而僅用於編譯程式或工具程式執行時提供資訊。

2) 我們在註解中應該採取什麼樣的一種保持策略呢?如果下圖說明所示,我們需要提供RetentionPolicy列舉型態。


檢視JDK文件中的RetentionPolicy

java.lang.annotation 
Enum RetentionPolicy
Annotation retention policy. The constants of this enumerated type describe the various policies for retaining annotations. They are used in conjunction with the Retention meta-annotation type to specify how long annotations are to be retained. 

[Retention是一個註解,裡面有一個列舉RetentionPolicy,這個列舉決定了Retention這個註解應該如何去保持,預設情況下,這個註解資訊會被保持到class檔案當中。]

有三個列舉常量如下圖所示:


預設情況下是第一種Class列舉常量。

5. 現在利用註解給我們提供的Retention和RetentionPloicy講一個例子


這邊我們檢視JDK Doc文件 Override註解、Deprecated註解、SuppressWarnings註解,檢視他們分別是對應的註解時機是以上三種的哪一種。

比如Override註解:表示在編譯的時候被丟棄,也就是僅僅是定義在原始檔中的。類似檢視其他兩個。

@Target(value=METHOD)

@Retention(value=SOURCE)

public @interface Override

如果註解能在執行的時候保留下來,我們就可以通過反射的機制將其資訊讀取出來,下面就是用反射的API的來提取註解資訊


檢視JDK Doc文件中的AnnotatedElement可以發現反射中的Class、Constructor、Field、Method、Package等類別,都實現了AnnotatedElement介面。上圖的這幾個方法都是很重要的。

package com.ahuier.annotation;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/*
 * 使用Retention修飾這個註解,
 * 告訴這個註解在使用的時候僅僅用在原始檔中,還是可以用到.Class檔案中,還是即可以用到.Class檔案,又能在執行過程中通過反射的方式讀取出來
 */
@Retention(RetentionPolicy.CLASS)
public @interface MyAnnotation {
	String hello() default "ahuier";
	String world();
}
package com.ahuier.annotation;

@MyAnnotation(hello = "beijing", world = "shanghai")
public class MyTest {
	
	@MyAnnotation(hello = "tianjin", world = "shangdi")
	@Deprecated
	@SuppressWarnings("unchecked")       //一個方法可以有多個註解所修飾
	public void output(){
		System.out.println("output something!");
	}
}