目錄
Annotation(註解)
meta-annotation(元註解)
@Target註解
@Retention註解
@Documented註解
@Inherited註解
註解應用舉例
Annotation(註解)
從JDK 1.5開始, Java增加了對元數據(MetaData)的支持,也就是 Annotation(註解)。
註解其實就是代碼裏的特殊標記,它用於替代配置文件:傳統方式通過配置文件告訴類如何運行,有了註解技術後,開發人員可以通過註解告訴類如何運行。在Java技術裏註解的典型應用是:可以通過反射技術去得到類裏面的註解,以決定怎麼去運行類。
註解可以標記在包、類、屬性、方法,方法參數以及局部變量上,且同一個地方可以同時標記多個註解。
// 抑制編譯期的未指定泛型、未使用和過時警告
@SuppressWarnings({ “rawtypes”, “unused”, “deprecation” })
// 重寫
@Override
meta-annotation(元註解)
除了直接使用JDK 定義好的註解,我們還可以自定義註解,在JDK 1.5中提供了4個標準的用來對註解類型進行註解的註解類,我們稱之爲 meta-annotation(元註解),他們分別是:
@Target
@Retention
@Documented
@Inherited
我們可以使用這4個元註解來對我們自定義的註解類型進行註解,接下來,我們挨個對這4個元註解的作用進行介紹。
@Target註解
Target註解的作用是:描述註解的使用範圍(即:被修飾的註解可以用在什麼地方) 。
Target註解用來說明那些被它所註解的註解類可修飾的對象範圍:註解可以用於修飾 packages、types(類、接口、枚舉、註解類)、類成員(方法、構造方法、成員變量、枚舉值)、方法參數和本地變量(如循環變量、catch參數),在定義註解類時使用了@Target 能夠更加清晰的知道它能夠被用來修飾哪些對象,它的取值範圍定義在ElementType 枚舉中。
public enum ElementType {
TYPE, // 類、接口、枚舉類
FIELD, // 成員變量(包括:枚舉常量)
METHOD, // 成員方法
PARAMETER, // 方法參數
CONSTRUCTOR, // 構造方法
LOCAL_VARIABLE, // 局部變量
ANNOTATION_TYPE, // 註解類
PACKAGE, // 可用於修飾:包
TYPE_PARAMETER, // 類型參數,JDK 1.8 新增
TYPE_USE // 使用類型的任何地方,JDK 1.8 新增
}
@Retention註解
Reteniton註解的作用是:描述註解保留的時間範圍(即:被描述的註解在它所修飾的類中可以被保留到何時) 。
Reteniton註解用來限定那些被它所註解的註解類在註解到其他類上以後,可被保留到何時,一共有三種策略,定義在RetentionPolicy枚舉中。
public enum RetentionPolicy {
SOURCE, // 源文件保留
CLASS, // 編譯期保留,默認值
RUNTIME // 運行期保留,可通過反射去獲取註解信息
}
爲了驗證應用了這三種策略的註解類有何區別,分別使用三種策略各定義一個註解類做測試。
@Retention(RetentionPolicy.SOURCE)
public @interface SourcePolicy {
}
@Retention(RetentionPolicy.CLASS)
public @interface ClassPolicy {
}
@Retention(RetentionPolicy.RUNTIME)
public @interface RuntimePolicy {
}
用定義好的三個註解類分別去註解一個方法。
public class RetentionTest {
@SourcePolicy
public void sourcePolicy() {
}
@ClassPolicy
public void classPolicy() {
}
@RuntimePolicy
public void runtimePolicy() {
}
}
如圖所示,通過執行 javap -verbose RetentionTest命令獲取到的RetentionTest 的 class 字節碼內容如下。
{
public retention.RetentionTest();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #1 // Method java/lang/Object.""😦)V
4: return
LineNumberTable:
line 3: 0
public void sourcePolicy();
flags: ACC_PUBLIC
Code:
stack=0, locals=1, args_size=1
0: return
LineNumberTable:
line 7: 0
public void classPolicy();
flags: ACC_PUBLIC
Code:
stack=0, locals=1, args_size=1
0: return
LineNumberTable:
line 11: 0
RuntimeInvisibleAnnotations:
0: #11()
public void runtimePolicy();
flags: ACC_PUBLIC
Code:
stack=0, locals=1, args_size=1
0: return
LineNumberTable:
line 15: 0
RuntimeVisibleAnnotations:
0: #14()
}
從 RetentionTest 的字節碼內容我們可以得出以下兩點結論:
1. 編譯器並沒有記錄下 sourcePolicy() 方法的註解信息;
2. 編譯器分別使用了 RuntimeInvisibleAnnotations 和 RuntimeVisibleAnnotations 屬性去記錄了classPolicy()方法 和 runtimePolicy()方法 的註解信息;
@Documented註解
Documented註解的作用是:描述在使用 javadoc 工具爲類生成幫助文檔時是否要保留其註解信息。
爲了驗證Documented註解的作用到底是什麼,我們創建一個帶有 @Documented 的自定義註解類。
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyDocumentedtAnnotation {
public String value() default "這是@Documented註解爲文檔添加的註釋";
}
再創建一個 MyDocumentedTest 類。
@MyDocumentedtAnnotation
public class MyDocumentedTest {
@Override
@MyDocumentedtAnnotation
public String toString() {
return this.toString();
}
}
接下來,使用以下命令爲 MyDocumentedTest 類生成幫助文檔。
命令執行完成之後,會在當前目錄下生成一個 doc 文件夾,其內包含以下文件。
查看 index.html 幫助文檔,可以發現在類和方法上都保留了 MyDocumentedtAnnotation 註解信息。
修改 MyDocumentedtAnnotation 註解類,去掉上面的 @Documented 註解。
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface MyDocumentedtAnnotation {
public String value() default "這是@Documented註解爲文檔添加的註釋";
}
重新生成幫助文檔,此時類和方法上的 MyDocumentedtAnnotation 註解信息都不見了。
@Inherited註解
Inherited註解的作用是:使被它修飾的註解具有繼承性(如果某個類使用了被@Inherited修飾的註解,則其子類將自動具有該註解)。
接下來我們使用代碼來進行測試,首先創建一個被@Inherited修飾的註解類MyInheritedAnnotation。
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyInheritedAnnotation {
public String name() default "pengjunlee";
}
創建一個帶有 MyInheritedAnnotation 註解的父類和一個無任何註解的子類。
@MyInheritedAnnotation(name=“parent”)
public class Parent {
}
public class Child extends Parent{
public static void main(String[] args) {
Class<Child> child=Child.class;
MyInheritedAnnotation annotation = child.getAnnotation(MyInheritedAnnotation.class);
System.out.println(annotation.name());
}
}
運行程序,打印結果如下:
parent
註解應用舉例
首先自定義一個註解類。
package com.pengjunlee;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyAnnotation {
public String name() default "pengjunlee";
}
在 AnnotationTest 中使用反射獲取註解信息。
package com.pengjunlee;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
@MyAnnotation(name = “name of type”)
public class AnnotationTest {
@MyAnnotation(name = "name of method")
public String hello() {
return "hello";
}
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
Class<AnnotationTest> annotationTest = AnnotationTest.class;
// 獲取類上的所有註解
Annotation[] annotations = annotationTest.getAnnotations();
for (Annotation annotation : annotations) {
// 獲取註解的全類名
System.out.println(annotation.annotationType().getName());
}
// 獲取 hello() 方法
Method method = annotationTest.getMethod("hello", new Class[] {});
// hello() 方法上是否有 MyAnnotation 註解
if (method.isAnnotationPresent(MyAnnotation.class)) {
// 獲得註解
MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
// 獲取註解的內容
System.out.println(annotation.name());
}
}
}
運行程序,打印結果如下:
com.pengjunlee.MyAnnotation
name of method
————————————————
版權聲明:本文爲CSDN博主「pengjunlee」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/pengjunlee/article/details/79683621