如果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類如下方法:
- A getAnnotation(Class annotationClass):如果此元素存在 annotationClass類型的註解,則返回註解,否則返回null。
- Annotation[] getAnnotations():返回此元素上存在的所有註解。
- Annotation[] getDeclaredAnnotations():返回直接存在於此元素上的所有註解。與getAnnotations() 區別在於該方法將不返回繼承的註釋。
- boolean isAnnotationPresent(Class<? extends Annotation> annotationClass):如果此元素上存在 annotationClass類型的註解,則返回true,否則返回false。
- boolean isAnnotation():如果此Class對象表示一個註解類型則返回true。
在運行時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,讀取註解描述: 年齡
以上內容僅供參考學習,如有侵權請聯繫我刪除!
如果這篇文章對您有幫助,左下角的大拇指就是對博主最大的鼓勵。
您的鼓勵就是博主最大的動力!