Java自定義註解

如果Java SE提供的11內置註解不能滿足你的需求,可以自定義註解,註解本質是一種接口,它 是java.lang.annotation.Annotation接口的子接口,是引用數據類型。

一、聲明註解

聲明自定義註解可以使用@interface關鍵字實現,最簡單形式的註解示例代碼如下:

public @interface Marker{

}

上述代碼聲明一個Marker註解,@interface聲明一個註解類型,它前面的訪問限定修飾符與類一樣有兩 種:公有訪問權限和默認訪問權限。
Marker註解中不包含任何的成員,這種註解稱爲標記註解(Marked Annotation),基本註解中的 @Override就屬於標記註解。根據需要註解中可以包含一些成員,示例代碼如下:

//單值註解 
@interface MyAnnotation { 
	String value(); 
}

代碼中聲明MyAnnotation 註解,它有一個成員value,注意value後面是有一對小括號,value前面的是 數據類型。成員也可以有訪問權限修飾符,但是隻能是公有權限和默認權限。
註解中的成員也可以有默認值,示例代碼如下:

//帶有默認值註解 
@interface MyAnnotation1 {

String value() default "註解信息";

int count() default 0;

}

通過關鍵字default指定默認值。使用這些註解示例代碼如下:

@Marker
public class HelloWorld {
	@MyAnnotation(value = "Annotation") 
	private String info = "";
	
	@MyAnnotation1(count = 10) 
	public static void main(String[] args) {
	}
}

默認情況下註解可以修飾任意的程序元素(類、接口、成員變量、成員方法和數據類型等)。

二、使用元註解案例

上面聲明註解只是最基本形式的註解,對於複雜的註解可以在聲明註解時使用元註解。下面通過一 個案例介紹一下在自定義註解中使用元註解,在本案例中定義了兩個註解。

先看看第一個註解MyAnnotation,它用來修飾類或接口,MyAnnotation代碼如下:

import java.lang.annotation.ElementType; 
import java.lang.annotation.Retention; 
import java.lang.annotation.RetentionPolicy; 
import java.lang.annotation.Documented; 
import java.lang.annotation.Target;

@Documented 
@Target({ ElementType.TYPE }) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface MyAnnotation { 
	String description(); 
}

第二個註解MemberAnnotation,它用來類中成員變量和成員方法,MemberAnnotation代碼如下:

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; 
@Documented 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ ElementType.FIELD, ElementType.METHOD }) 
public @interface MemberAnnotation {
	Class<?> type() default void.class;
	String description(); 
}

使用了MyAnnotation和MemberAnnotation註解是Person類,Person類代碼如下:

@MyAnnotation(description = "這是一個測試類") 
public class Person {
	@MemberAnnotation(type = String.class, description = "名字") 
	private String name;

	@MemberAnnotation(type = int.class, description = "年齡") 
	private int age;
	
	@MemberAnnotation(type = String.class, description = "獲得名字") 
	public String getName() { 
		return name; 
	}
	
	@MemberAnnotation(type = int.class, description = "獲得年齡") 
	public int getAge() { 
		return age; 
	}
	@MemberAnnotation(description = "設置姓名和年齡") 
	public void setNameAndAge(String name, int age) {
		this.name = name;
		this.age = age; 
	}
	@Override 
	public String toString() { 
		return "Person [name=" + name + ", age=" + age + "]"; 
	}
}

使用註解時如果當前類與註解不在同一個包中,則需要將註解引入。

三、讀取運行時註解信息案例

註解是爲工具讀取信息而準備的。有些工具可以讀取源代碼文件中的註解信息;有的可以讀取字節碼 文件中的註解信息;有的可以在運行時讀取註解信息。但是讀取這些註解信息的代碼都是一樣的,區 別隻在於自定義註解中@Retention的保留策略不同。
讀取註解信息需要反射相關API,Class類如下方法:

在運行時Person類中註解信息代碼如下:

import java.lang.reflect.Field; 
import java.lang.reflect.Method;

public class HelloWorld {
	public static void main(String[] args) {
		try { 
			Class<?> clz = Class.forName("xxx.Person");
			// 讀取類註解 
			if (clz.isAnnotationPresent(MyAnnotation.class)) { 
				MyAnnotation ann = (MyAnnotation)clz.getAnnotation(MyAnnotation.class);
				System.out.printf("類%s,讀取註解描述: %s \n", clz.getName(), ann.description()); 
			}
			
			// 讀取成員方法的註解信息 
			Method[] methods = clz.getDeclaredMethods(); 
			for (Method method : methods) {
				if (method.isAnnotationPresent(MemberAnnotation.class)) { 
					MemberAnnotation ann = method.getAnnotation(MemberAnnotation.class);
					System.out.printf("方法%s,讀取註解描述: %s \n", method.getName(), ann.description()); 
				} 
			}
			
			// 讀取成員變量的註解信息 
			Field[] fields = clz.getDeclaredFields(); 
			for (Field field : fields) {
				if (field.isAnnotationPresent(MemberAnnotation.class)) {
	 				MemberAnnotation ann = field.getAnnotation(MemberAnnotation.class);
				    System.out.printf("成員變量%s,讀取註解描述: %s \n", field.getName(), ann.description()); 
			  	}
			} 
		} catch (Exception e) {
			e.printStackTrace(); 
		}
	}
}

運行結果如下:

類com.a51work6.Person,讀取註解描述: 這是一個測試類 
方法getName,讀取註解描述: 獲得名字 
方法getAge,讀取註解描述: 獲得年齡 
方法setNameAndAge,讀取註解描述: 設置姓名和年齡 
成員變量name,讀取註解描述: 名字 
成員變量age,讀取註解描述: 年齡

以上內容僅供參考學習,如有侵權請聯繫我刪除!
如果這篇文章對您有幫助,左下角的大拇指就是對博主最大的鼓勵。
您的鼓勵就是博主最大的動力!

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