一. 註解的本質
「java.lang.annotation.Annotation」接口中有這麼一句話,用來描述『註解』。
The common interface extended by all annotation types
所有的註解類型都繼承自這個普通的接口(Annotation)
這句話有點抽象,但卻說出了註解的本質。我們看一個 JDK 內置註解的定義:
<code>@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
/<code>
這是註解 @Override 的定義,其實它本質上就是:
<code>public interface Override extends Annotation{
}
/<code>
沒錯,註解的本質就是一個繼承了 Annotation 接口的接口。有關這一點,你可以去反編譯任意一個註解類,你會得到結果的。
一個註解準確意義上來說,只不過是一種特殊的註釋而已,如果沒有解析它的代碼,它可能連註釋都不如。
解析一個類或者方法的註解往往有兩種形式,一種是編譯期直接的掃描,一種是運行期反射。
二. 元註解
『元註解』是用於修飾註解的註解,通常用在註解的定義上。
JAVA 中有以下幾個『元註解』:
- @Target:註解的作用目標
- @Retention:註解的生命週期
- @Documented:註解是否應當被包含在 JavaDoc 文檔中
- @Inherited:是否允許子類繼承該註解
1. @Target
@Target 註解指明該註解可以作用哪些對象上。
<code>@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
/**
* Returns an array of the kinds of elements an annotation type
* can be applied to.
* @return an array of the kinds of elements an annotation type
* can be applied to
*/
ElementType[] value();
}
/<code>
註解接收一個ElementType數組,ElementType是一個枚舉,成員如下:
- ElementType.TYPE:允許被修飾的註解作用在類、接口和枚舉上
- ElementType.FIELD:允許作用在屬性字段上
- ElementType.METHOD:允許作用在方法上
- ElementType.PARAMETER:允許作用在方法參數上
- ElementType.CONSTRUCTOR:允許作用在構造器上
- ElementType.LOCAL_VARIABLE:允許作用在本地局部變量上
- ElementType.ANNOTATION_TYPE:允許作用在註解上
- ElementType.PACKAGE:允許作用在包上
- ElementType.TYPE_PARAMETER:允許作用在類型參數上
- ElementType.TYPE_USE:允許作用在類型上
2. @Retention
@Retention 用於指明當前註解的生命週期
<code>@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
/**
* Returns the retention policy.
* @return the retention policy
*/
RetentionPolicy value();
}
/<code>
註解接收一個RetentionPolicy數據,RetentionPolicy是個枚舉,成員如下:
- RetentionPolicy.SOURCE:當前註解編譯期可見,不會寫入 class 文件
- RetentionPolicy.CLASS:類加載階段丟棄,會寫入 class 文件
- RetentionPolicy.RUNTIME:永久保存,可以反射獲取
三. JAVA 的內置三大註解
- @Override
- @Deprecated 標識類或方法不再推薦使用
- @SuppressWarnings 主要用來壓制 java 的警告
四. 實現一個自己的註解
定義一個註解:
<code>@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface HelloAnnotation {
String value() default "Hello annotation!";
}
/<code>
使用這個註解:
<code>public class UseAnnotation {
@HelloAnnotation
public void hello() {
System.out.println("hello");
}
@HelloAnnotation("Hello world!")
public void helloWorld() {
System.out.println("Hello world!");
}
}
/<code>
註解最重要的部分在於對註解的處理。註解處理器就是通過反射機制獲取被檢查方法上的註解信息,然後根據註解元素的值進行特定的處理。如果沒有註解處理器,註解就是個註釋,或者連註釋都不如。
處理這個註解:
<code>public class Test {
public static void main(String[] args) {
testAnnotation(UseAnnotation.class);
}
private static void testAnnotation(Class> cl) {
for (Method m : cl.getDeclaredMethods()) {
HelloAnnotation ha = m.getAnnotation(HelloAnnotation.class);
if (ha != null) {
System.out.println("Found My Annotation: " + ha.value());
}
}
}
}
/<code>
輸出結果:
<code>Found My Annotation: Hello annotation!
Found My Annotation: Hello world!/<code>
Java程序員福利:我把2019近一年經歷過的Java崗位面試,和一些刷過的面試題都做成了PDF,PDF都是可以免費分享給大家的,關注私信我:【101】,免費領取!
閱讀更多 Java架構師丨蘇先生 的文章