Annotation

從JDK5開始,Java增加了對元數據的支持,也就是Annotation,它也被稱作註釋。

  基本的Annotation:

  限定重寫父類方法:@Override

@Override就是用來指定方法的重寫,它強制一個子類必須覆蓋父類的方法,這個大家比較熟悉就不多說了。

  已過時的標記:@Deprecated

如果你的程序元素被標記成Deprecated的話,那麼你在調用的時候該程序元素就會被加線,證明該方法過時,不建議被使用。

public class TestDeprecate {

	@Deprecated
	public void sayHello() {
		
		System.out.println("Hello");
	}
	
	public void sayWorld() {
		
		sayHello();
	}
}


  抑制編譯器的警告:@SuppressWarnings

如果你想取消顯示指定的編譯器警告的話,就可以用該Annotation,最常見的是在泛型上,下面就舉這個例子:

@SuppressWarnings(value="unchecked")
public class TestSuppressWarnings {

	public static void main(String[] args) {
		
		List<String> list = new ArrayList();
	}
}

這樣就取消了沒有使用泛型的警告。

   自定義Annotation:

定義一個新的Annotation類型要使用@interface關鍵字,下面就是一個簡單的Annotation類型:

public @interface Hello {

}

當然自定義的Annotation還可以帶成員變量,它的成員變量在Annotation定義一無形參的方法形式來聲明的,其方法名和返回值定義了該成員變量的名字和類型:

public @interface Hello {

	String name();
	int age();
}

簡單的實際應用:

public class World {

	@Hello(name="guo", age=20)
	public void say() {
		
		System.out.println("World");
	}
}

通過簡單的key=value形式就給成員變量賦值了

當然自定義的Annotation的成員變量可以設定默認值:

public @interface Hello {

	String name() default "guo";
	int age() default 20;
}

  提取Annotation信息:

被Annotation修飾的程序元素我們可以根據Annotation提取出裏面的信息:

下面先介紹=幾個方法:

getAnnotation(Class<T> annltationClass):返回該程度元素上存在的指定類型的註釋,如果該類的註釋不存在就返回null

Annotation[] getAnnotations():返回該程序元素上存在的所有註釋

boolean isAnnotationPresent(Class<? extends Annotation> annotationClass):判斷該程序上元素上是否存在指定類型的註釋,如果存在即true,否則false

下面我們用反射的知識去幫助提取出相應的信息:

public class World {

	@Hello(name="guo", age=20)
	public void say() {
		
		System.out.println("World");
	}
	
	public static void main(String[] args) {
		
		try {
			
			Annotation[] annotation = Class.forName("com.xujianguo.annotation.World").getMethod("say").getAnnotations();

			for(Annotation a : annotation) {
				
				System.out.println(a.toString());
				
				if(a instanceof Hello) {
					
					System.out.println("-------------------");
					System.out.println(((Hello)a).name());
					System.out.println(((Hello)a).age());
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

這裏要嚴重提醒的是:如果要用反射就拿Annotation的信息的話,就可以在定義的Annotation上加上@Retention:

@Retention(value=RetentionPolicy.RUNTIME)
public @interface Hello {

	String name() default "guo";
	int age() default 20;
}

這樣保證了在JVM會保留該Annotation,就可以通過反射獲取信息了。

  先面模擬一下Junit的單元測試:

定義@TestSimulation這個新的Annotation:

@Retention(value=RetentionPolicy.RUNTIME)
public @interface TestSimulation {

}

在Communication類中應用@TestSimulation:

public class Communication {

	@TestSimulation
	public void say() {
		
		System.out.println("hello");
	}
	
	public void call() {
		
		System.out.println("call you");
	}
	
	@TestSimulation
	public void look() {
		
		System.out.println("look");
	}
}

定義工具類解析:

public class AnnotationUtil {

	public static void processAnnotation(String path) {
		
		try {
			
			Class clazz = Class.forName(path);
			Object o = clazz.newInstance();
			Method[] methods = clazz.getMethods();
			
			for(Method m : methods) {
				
				if(m.isAnnotationPresent(TestSimulation.class)) {
					
					m.invoke(o);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

測試類:

public class StartUp {

	public static void main(String[] args) {
		
		AnnotationUtil.processAnnotation("com.xujianguo.annotation.Communication");
	}
}

測試結果:

hello
look

 

 

 

 

 

 

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