Java Annotations

本文譯自Java Annotations


Java Annotation Purposes

一般來說,Java Annotations有以下三種用途:

  • Compiler instructions
  • Build-time instructions
  • Runtime instructions

構建工具能夠掃描Java代碼中的annotations並基於這些annotations來生成源碼或者文件。一般而言,編譯後的Java代碼中不會包含annotations,但是我們也可以定義運行時可見的annotations(這些annotations可以通過Java反射機制被訪問到,並向我們的程序或者第三方API發出指令)。



創建我們自己的註解

每一個annotation都定義在其自己的.java文件中,就像定義類或者接口那樣,如下

public @interface MyAnnotation {
	public String name();
	public String value();
	int age();
	String[] newNames();
}
註解中的element可以是primitive types,或者是數組,但是不能是複合類型。
如果註解有element,則在使用該註解時要指定每一個element的值,如

@MyAnnotation(name="NAME", value="VALUE",
		age=18, newNames={"1", "2", "3"})
public class Hello {
	public static void main(String[] args){	
		
	}	
}

當在定義註解時爲某個element指定了默認值時,則使用該註解時可以不指定該element的值,如下

public @interface MyAnnotation {
	public String name() default "OK";
	public String value();
	int age();
	String[] newNames();
}
@MyAnnotation(value="VALUE", age=18, newNames={"1", "2", "3"})
public class Hello {
	public static void main(String[] args){	
		
	}	
}


@Retention

對於我們自定義的註解,可以通過@Retention註解來指定是否使其在運行時可見(通過反射),如下

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

@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnnotation {
	public String name() default "OK";
	public String value();
	int age();
	String[] newNames();
}
其中,RetentionPolicy類包含了三種不同的值:

  • RetentionPolicy.RUNTIME : 指定本annotation在運行時可見
  • RetentionPolicy.CLASS : 指定本annotation將被存儲在.class文件中,且在運行時不可見。如果沒有指定任何retention策略,則RetentionPolicy.CLASS將是默認的策略
  • RetentionPolicy.SOURCE : 指定本annotation只存在於源代碼中,在.class文件中不存在,且在運行時不可見。如果希望只讓構建工具來利用這些annotation,可以使用該策略


@Target

使用@Target註解可以限制我們自定義的annotation只能修飾哪些Java元素,如下

import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Target({ElementType.METHOD})  // 限制本annotation只能用於Java中的方法
public @interface MyAnnotation {
	public String name() default "OK";
	public String value();
	int age();
	String[] newNames();
}
此外,ElementType類還有以下值:

  • ElementType.ANNOTATION_TYPE
  • ElementType.CONSTRUCTOR
  • ElementType.FIELD
  • ElementType.LOCAL_VARIABLE
  • ElementType.METHOD
  • ElementType.PACKAGE
  • ElementType.PARAMETER
  • ElementType.TYPE

其中,ElementType.TYPE可以應用於任何Java類型,包括class,interface, enum, 以及annotation。



@Inherited

如果一個annotation被@Inherited修飾,且類Base被該annotation修飾了,那麼對於任何繼承了類Base的子類(不妨稱之爲Derived類),類Derived也自動繼承了該annotation。如下:

import java.lang.annotation.Inherited;

@Inherited
public @interface MyAnnotation {
}
@MyAnnotation
public class A {
}
public class B extends A {

}




利用Java Reflection訪問Annotations

訪問Class Annotations

如果修飾某個類的annotations在定義是指定了@Retention(RetentionPolicy.RUNTIME)策略,那麼可以在運行時訪問該類中的annotations。

訪問全部的annotations

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

@Retention(RetentionPolicy.RUNTIME)	//注意,必須有本指令,否則在運行時本annotation是不可見的 
public @interface MyAnnotation {
	public String name();
	public String value();
}
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention(RetentionPolicy.RUNTIME)
public @interface AnotherAnnotation {
	public String anotherName();
	public String anotherValue();
}
import java.lang.annotation.Annotation;

@MyAnnotation(name="ccc", value="love")
@AnotherAnnotation(anotherName="xt", anotherValue="Real Love")
public class A {
	public static void main(String[] args) {
		Class aClass = A.class;
		Annotation[] annotations = aClass.getAnnotations();
		
		for (Annotation annotation : annotations) {
			if (annotation instanceof MyAnnotation) {
				MyAnnotation myAnnotation = (MyAnnotation)annotation;
				System.out.println("name:" + myAnnotation.name());
				System.out.println("value:" + myAnnotation.value());
			} else if (annotation instanceof AnotherAnnotation) {
				AnotherAnnotation anotherAnnotation = (AnotherAnnotation)annotation;
				System.out.println("another name: " + anotherAnnotation.anotherName());
				System.out.println("another value: " + anotherAnnotation.anotherValue());
			}			
		}
	}
}


訪問某個指定的Annotation

import java.lang.annotation.Annotation;

@MyAnnotation(name="ccc", value="love")
@AnotherAnnotation(anotherName="xt", anotherValue="Real Love")
public class A {
	public static void main(String[] args) {
		Class aClass = A.class;
		Annotation annotation = aClass.getAnnotation(MyAnnotation.class);
		if (annotation instanceof MyAnnotation) {
			MyAnnotation myAnnotation = (MyAnnotation)annotation;
			System.out.println("name:" + myAnnotation.name());
			System.out.println("name:" + myAnnotation.value());
		}
	}
}


訪問Method Annotations

訪問一個Method的全部Annotations

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class A {
	public static void main(String[] args) throws SecurityException, NoSuchMethodException {
		Class aClass = A.class;
		Method method = aClass.getMethod("func",null);
		
		Annotation[] annotations = method.getAnnotations();
		for (Annotation annotation : annotations) {
			if (annotation instanceof MyAnnotation) {
				MyAnnotation myAnnotation = (MyAnnotation)annotation;
				System.out.println("name: " + myAnnotation.name());
				System.out.println("value: " + myAnnotation.value());
			} else if (annotation instanceof AnotherAnnotation) {
				AnotherAnnotation anotherAnnotation = (AnotherAnnotation)annotation;
				System.out.println("name: " + anotherAnnotation.anotherName());
				System.out.println("value: " + anotherAnnotation.anotherValue());
			}			
		}
	}
	
	@MyAnnotation(name="000", value="111")
	@AnotherAnnotation(anotherName="aaa", anotherValue="bbb")
	public void func() {		
	}
}

訪問一個Method的指定Annotation

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

public class A {
	public static void main(String[] args) throws SecurityException, NoSuchMethodException {
		Class aClass = A.class;
		Method method = aClass.getMethod("func", null);
		
		Annotation annotation = method.getAnnotation(AnotherAnnotation.class);
		if (annotation instanceof AnotherAnnotation) {
			AnotherAnnotation anotherAnnotation = (AnotherAnnotation)annotation;
			System.out.println("name: " + anotherAnnotation.anotherName());
			System.out.println("value: " + anotherAnnotation.anotherValue());
		}			
	}
	
	@MyAnnotation(name="000", value="111")
	@AnotherAnnotation(anotherName="aaa", anotherValue="bbb")
	public void func() {		
	}
}

訪問方法參數的annotations

MyAnnotation與AnotherAnnotation的定義如上所述,下面再增加一個OtherAnnotation

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

@Retention(RetentionPolicy.RUNTIME)
public @interface OtherAnnotation {
	public String otherName();
	public int otherValue();
}

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class A {
	public static void main(String[] args) throws SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
		Class aClass = A.class;
		Method method = aClass.getMethod("func", new Class[]{String.class, int.class});
		/* method.getParameterAnnotations()返回的是一個二維Annotation數組
		 * 第一個維度代表該method的一個參數,第二個維度代表該參數的annotations
		 * 所以該二維Annotation數組第一維度的數量 == 該method的參數數量 */		
		Annotation[][] annotationArray = method.getParameterAnnotations();		
		for (Annotation[] annotations : annotationArray) { 
			// 每一個annotations對象代表了一個參數的全部註解
			for (Annotation annotation : annotations) {
				if (annotation instanceof MyAnnotation) {
					MyAnnotation myAnnotation = (MyAnnotation)annotation;
					System.out.println("name: " + myAnnotation.name());
					System.out.println("value: " + myAnnotation.value());
				} else if (annotation instanceof AnotherAnnotation) {
					AnotherAnnotation anotherAnnotation = (AnotherAnnotation)annotation;
					System.out.println("anotherName: " + anotherAnnotation.anotherName());
					System.out.println("anotherValue: " + anotherAnnotation.anotherValue());
				}  else if (annotation instanceof OtherAnnotation) {
					OtherAnnotation otherAnnotation = (OtherAnnotation)annotation;
					System.out.println("otherName: " + otherAnnotation.otherName());
					System.out.println("otherValue: " + otherAnnotation.otherValue());
				} 
			}
		}
	}
	
	public static void func(
		@MyAnnotation(name="ccc", value="love")	
		@AnotherAnnotation(anotherName="AAA", anotherValue="BBB") String str,	// 參數一
		@MyAnnotation(name="ccc", value="love") 
		@OtherAnnotation(otherName="XXX", otherValue=325) int n) 				// 參數二
	{

	}
	
}


訪問field annotation

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class A {
	@MyAnnotation(name="m_x", value="xxx")
	@AnotherAnnotation(anotherName="m_y", anotherValue="yyy")
	@OtherAnnotation(otherName="m_z", otherValue=444)
	private String m_x;
	
	public static void main(String[] args) throws  NoSuchFieldException {
		Field field = A.class.getDeclaredField("m_x");
		Annotation[] annotations = field.getDeclaredAnnotations();
		
		for (Annotation annotation : annotations) {
			if (annotation instanceof MyAnnotation) {
				MyAnnotation myAnnotation = (MyAnnotation)annotation;
				System.out.println("name: " + myAnnotation.name() + ", value: " + myAnnotation.value());
			} else if (annotation instanceof AnotherAnnotation) {
				AnotherAnnotation anotherAnnotation = (AnotherAnnotation)annotation;
				System.out.println("anotherName: " + anotherAnnotation.anotherName() + ", anotherValue: " + anotherAnnotation.anotherValue());
			} else if (annotation instanceof OtherAnnotation) {
				OtherAnnotation otherAnnotation = (OtherAnnotation)annotation;
				System.out.println("otherName: " + otherAnnotation.otherName() + ", otherValue: " + otherAnnotation.otherValue());
			}
		}
	}	
}

還可以訪問指定的annotation

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;

public class A {
	@MyAnnotation(name="m_x", value="xxx")
	@AnotherAnnotation(anotherName="m_y", anotherValue="yyy")
	@OtherAnnotation(otherName="m_z", otherValue=444)
	private String m_x;
	
	public static void main(String[] args) throws  NoSuchFieldException {
		Field field = A.class.getDeclaredField("m_x");
		Annotation[] annotations = field.getDeclaredAnnotations();
		
		for (Annotation annotation : annotations) {
			if (annotation instanceof MyAnnotation) {
				MyAnnotation myAnnotation = (MyAnnotation)annotation;
				System.out.println("name: " + myAnnotation.name() + ", value: " + myAnnotation.value());
			} else if (annotation instanceof AnotherAnnotation) {
				AnotherAnnotation anotherAnnotation = (AnotherAnnotation)annotation;
				System.out.println("anotherName: " + anotherAnnotation.anotherName() + ", anotherValue: " + anotherAnnotation.anotherValue());
			} else if (annotation instanceof OtherAnnotation) {
				OtherAnnotation otherAnnotation = (OtherAnnotation)annotation;
				System.out.println("otherName: " + otherAnnotation.otherName() + ", otherValue: " + otherAnnotation.otherValue());
			}
		}
	}	
}










發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章