JAVA語言基礎回顧:基本註解

本文主要向大家介紹了JAVA語言基礎回顧:基本註解,通過具體的內容向大家展示,希望對大家學習JAVA語言有所幫助。

概念

從 JDK 5 開始,Java 增加了對元數據(MetaData)的支持,也就是 Annotation,即註解。

註解是代碼裏的特殊標記,這些標記可以在編譯、類加載、運行時被讀取,並執行相應的處理。

通過使用註解,開發人員可以在不改變原有邏輯的情況下,在源文件中嵌入一些補充信息。

基本註解

@Override:限定重寫父類方法

用於表示一個子類的方法重寫了父類的方法,此註解只能修飾方法。

@Deprecated:標記已過時

用於表示某個程序元素(類、方法)已過時,當程序使用已過時的類、方法時,編譯器會給出警告。

@SuppressWarnings:抑制編譯器警告

被該註解修飾的元素以及它的所有子元素會取消顯示指定的編譯器警告。

元註解(Meta Annotation)

定義:元註解就是修飾註解的註解。

@Retention

只能用於修飾註解,用於指定被修飾的註解可以保留多長時間。

使用 @Retention 必須爲其 value 賦值,其值爲枚舉類型 RetentionPolicy。

RetentionPolicy.CLASS:編譯器把 Annotation 記錄在 class 文件中,當運行程序時, JVM 不可獲取註解信息。 RetentionPolicy.RUNTIME:編譯器把 Annotation 記錄在 class 文件中,當運行程序時, JVM 可以獲取註解信息,程序也可以通過反射獲取該註解信息。 **RetentionPolicy.SOURCE:**Annotation 只保留在源代碼中,編譯器直接丟棄這種註解。

@Retention(RetentionPolicy.RUNTIME)

public @interface Test {}

@Target

只能用於修飾註解,用於指定被修飾的 Annotation 能用於修飾哪些程序元素。

使用 @Target 必須爲其 value 賦值,其值爲枚舉類型 ElementType。

ElementType.TYPE:指定該策略的 Annotation 可以修飾類、接口或枚舉定義。ElementType.FIELD:指定該策略的 Annotation 只能修飾成員變量。ElementType.LOCAL_VARIABLE:指定該策略的 Annotation 只能修飾局部變量。ElementType.METHOD:指定該策略的 Annotation 只能修飾方法。 ElementType.PARAMETER:指定該策略的 Annotation 只能修飾參數。 ElementType.CONSTRUCTOR:指定該策略的 Annotation 只能修飾構造器。 ElementType.PACKAGE:指定該策略的 Annotation 只能修飾包定義。ElementType.ANNOTATION_TYPE:指定該策略 Annotation 只能修飾 Annotation。

@Target(ElementType.TYPE)

public @interface Test {}

@Documented

@Documented 修飾的 Annotation 類將被 JavaDoc 工具提取成文檔。

如果定義 Annotation 時使用 @Documented 修飾,則所有使用該 Annotation 修飾的程序元素的 API 文檔中將會包含該 Annotation 說明。

@Documented

public @interface Test {}

@Inherited

@Inherited 修飾的 Annotation 類將具有繼承性。

例如,@XXX 使用 @Inherited 修飾,如果某個類使用了 @XXX 註解,則其子類將自動被 @XXX 註解。

@Inherited

public @interface Test {}

Java 8 下的註解

類型註解(Type Annotation)

Java 8 爲 @Target 這個元註解的 value ElementType 新增了兩個枚舉值

ElementType.TYPE_USE ElementType.TYPE_PARAMETER

我們定義註解時就可以使用 @Target(ElementType.TYPE_USE) 來修飾,這種註解稱爲類型註解,可以使用在任何用到類型的地方,而不像在 Java 8 以前我們只能在定義程序元素時使用,例如定義類、定義接口等等。

// 定義類型註解

@Target(ElementType.TYPE_USE)

public @interface TypeAnnotation {}

// 使用

@TypeAnnotation

public class Test implements @TypeAnnotation Serializable {

public static void main(String[] args) {

String name = new @TypeAnnotation String("fancyluo");

}

}

可以看到,類型註解可以無處不在,這樣我們就可以使用類型註解來讓編譯器執行更嚴格的代碼檢查,從而提高程序的健壯性。但是,Java 8 並沒有爲類型註解提供檢查框架,需要開發者自行實現。

重複註解

在 Java 8 以前,同一個程序元素前只能使用一個相同類型的 Annotion,例如下面的例子是不行滴。

@RepeatableAnnotation(name = "阿道")

@RepeatableAnnotation(name = "fancyluo")

public class Test {}

如果需要使用多個相同類型的 Annotion,則需要定義一個 Annotation 容器來存放,容器的成員變量爲相應的 Annotation 數組。

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface RepeatableAnnotations {

RepeatableAnnotation[] value();

}

接下來定義要重複使用的 Annotion,需要使用 @Repeatable 來修飾,@Repeatable 的 value 爲 Annotation 容器。

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Repeatable(RepeatableAnnotations.class)

public @interface RepeatableAnnotation {

String name();

}

下面我們就可以使用相同類型的多個 Annotation 來修飾程序元素了,我們來看看 Java 8 與 Java 8 之前的寫法。

// Java 8 之前

@RepeatableAnnotations({

@RepeatableAnnotation(name = "fancyluo"),

@RepeatableAnnotation(name = "阿道")

})

public class Test {}

// Java 8

@RepeatableAnnotation(name = "fancyluo")

@RepeatableAnnotation(name = "阿道")

public class Test {}L

自定義 Annotation

定義新的 Annotation 類型可以使用 @interface 關鍵字。

public @interface Test {}

在默認情況下,Annotation 可以修飾任何程序元素,包括類、接口、方法等等。

@Test

public class User {

@Test

private void myMethod(){}

}

還可以爲 Annotation 以無形參的方法形式來聲明成員變量,方法名爲成員變量的名字,返回值爲成員變量的類型。

public @interface Phone {

String name();

int price();

}

@Phone(name = "IPhone X", price = 8888)

public class IPhone {}

當成員變量只有一個並且名爲 value 時,可以直接賦值。

public @interface Test {

String value();

}

@Test("fancyluo")

public class User {}

一旦爲 Annotation 聲明瞭成員變量,就需要在使用的時候爲該成員變量賦值,也可以爲其設置初始值,使用時則可以不賦值,設置初始值使用 default 關鍵字。

public @interface Person {

String name() default "fancyluo";

}

@Person

public class User {}

通過反射提取 Annotation 信息

從 Java 5 開始反射的 API 提供了讀取運行時註解的能力,當定義的註解使用@Retention(RetentionPolicy.RUNTIME) 修飾時,就可以在運行時使用反射提取該註解的信息。

// 定義註解

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

public @interface Phone {

String name();

int price();

}

// 修飾類

@Phone(name = "IPhone X",price = 8888)

public class IPhone {}

// 獲取註解信息

try {

// 使用全類名獲取類

Class clazz = Class.forName("com.fancyluo.test.IPhone");

// 獲取類的所有註解

Annotation[] annotationArray = clazz.getAnnotations();

for (Annotation annotation : annotationArray) {

// 打印註解信息

System.out.println(annotation);

// 如果要獲取註解的元數據,可以強轉成具體的註解來獲取

if (annotation instanceof Phone) {

Phone phone = (Phone) annotation;

System.out.println(phone.name() + ":" + phone.price());

}

}

} catch (ClassNotFoundException e) {

e.printStackTrace();

}

Class 這個類實現了 AnnotatedElement 接口,而這個接口裏面定義了一系列獲取註解的方法,所以我們就可以通過 Class 類來拿到註解的信息。不僅僅是 Class 類,AnnotatedElement 是所有程序元素的父接口,例如 Class、Method、Construtor 等。

下面我們來看看 AnnotatedElement 接口定義的各個方法的含義。

// 返回該程序元素上存在的指定類型的註解,不存在則返回 null

T getAnnotation(Class var1)

// Java 8 新增,嘗試獲取直接修飾該程序元素的指定類型的註解,不存在則返回 null

T getDeclaredAnnotation(Class var1)

// 返回該程序元素的所有註解

Annotation[] getAnnotations()

// 返回直接修飾該程序元素的所有註解

Annotation[] getDeclaredAnnotations()

// 判斷該程序元素上是否存在指定類型的註解,存在返回 true,否則返回 false

boolean isAnnotationPresent(Class annotationClass)

// 獲取修飾該程序元素、指定類型的多個 Annotation(用於 Java 8 新增的重複註解)

T[] getAnnotationsByType(Class annotationClass)

// 獲取直接修飾該程序元素、指定類型的多個 Annotation(用於 Java 8 新增的重複註解)

T[] getDeclaredAnnotationsByType(Class annotationClass)

相關文章