標記註解型別是沒有元素的註解型別,甚至沒有預設值。標記註解由註解處理工具使用。
public @interface Marker {
}
@Marker
public class Main{
}
元註解型別是註解型別,用於註解其他註解型別。元註解型別是Java類庫的一部分。它們在包java.lang.annotation
中宣告。
以下註解型別是元註解型別:
目標註釋型別注釋注釋型別以設定上下文以使用注釋型別。它只有一個名為value
的元素。 其值元素是java.lang.annotation.ElementType
列舉型別的陣列。下表列出了ElementType
列舉中的所有常數。
常數名稱 | 描述 |
---|---|
ANNOTATION_TYPE | 注釋另一個注釋型別宣告,使注釋型別為元注釋。 |
CONSTRUCTOR | 注釋建構函式。 |
FIELD | 注釋欄位和列舉常數。 |
LOCAL_VARIABLE | 注釋區域性變數。 |
METHOD | 注釋方法。 |
PACKAGE | 注釋包宣告。 |
PARAMETER | 註釋引數。 |
TYPE | 注釋類,介面(包括注釋型別)或列舉宣告。 |
TYPE_PARAMETER | 在通用類,介面,方法等中註釋型別引數。 |
TYPE_USE | 注釋所有型別的使用。 |
以下Version
注釋型別具有目標元註釋,它指定Version
注釋型別可以與只有三種型別的程式元素一起使用:任何型別(類,介面,列舉和注釋型別),建構函式和方法。
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
@Target({ ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.METHOD })
public @interface Version {
int major();
int minor();
}
Version
注釋不能用於除其Target
注釋中指定的三種型別之外的任何程式元素。
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
@Target({ ElementType.TYPE_USE })
@interface MyAnno {
}
@Target({ ElementType.TYPE_USE })
@interface MyAnno2 {
}
public class Main {
public void processData() throws @MyAnno Exception {
int roundedValue = (@MyAnno2 int) .02;
Main t = new @MyAnno Main();
}
}
如果不使用Target
注釋型別注釋注釋型別,則注釋型別可以用作任何宣告的修飾符,但型別引數宣告除外。
保留(Retention)注釋設定注釋型別的保留策略。注釋可以在三個級別保留 -
保留(Retention
)元註釋型別指定Java應如何保留註釋。如果注釋型別具有「僅限原始碼」保留策略,則在編譯到類檔案中時將刪除其範例。如果保留策略為「僅類檔案」,則其範例將保留在類檔案中,但不能在執行時讀取。
如果保留策略為「類檔案和執行時」,則注釋範例保留在類檔案中,並且它們可在執行時讀取。保留元註釋型別宣告一個名為value
的元素,它是java.lang.annotation.RetentionPolicy
列舉型別。
RetentionPolicy
列舉有三個常數:SOURCE
,CLASS
和 RUNTIME
,它們分別用於指定僅源,僅類和類執行時的保留策略。
以下程式碼在版本註釋型別上使用保留元注釋。它指定版本註釋應該在執行時可用。
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Target({ ElementType.TYPE, ElementType.CONSTRUCTOR, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@interface Version {
int major();
int minor();
}
如果不對注釋型別使用保留元註釋,則其保留策略僅預設為類檔案。則將無法在執行時讀取這些註釋。在類檔案中或在執行時,區域性變數宣告上的注釋永遠不可用,而不考慮注釋型別的保留策略。
繼承注釋型別是標記元註釋型別。如果注釋型別使用Inherited
元註釋注釋,則其範例將由子類宣告繼承。
如果使用注釋型別注釋除類宣告以外的任何元素,它沒有任何效果。以下程式碼顯示了@Inherited
元註釋型別的效果。
import java.lang.annotation.Inherited;
@interface Ann2 {
int id();
}
@Inherited
@interface Ann3 {
int id();
}
@Ann2(id = 1)
@Ann3(id = 2)
class A {
}
// Class B inherits Ann3(id=2) annotation from the class A
class B extends A {
}
文件化注釋型別是標記元註釋型別。如果注釋型別用Documented
註解,Javadoc工具將為其所有範例生成文件。
import java.lang.annotation.Documented;
@Documented
@interface Version {
int major();
int minor();
}
@Version(major = 1, minor = 0)
public class Main {
}
當使用Javadoc工具為Main
類生成文件時,Main
類宣告上的Version
注釋也會作為文件的一部分生成。
Java 8新增了可重複元註釋型別。如果在一個單獨的程式碼元素上重複使用它,注釋型別宣告必須用@Repeatable
來註解。
Repeatable
注釋型別只有一個名為value
的元素,其型別是另一個注釋型別的類型別。
import java.lang.annotation.Repeatable;
@interface LogHistory {
Log[] value();
}
@Repeatable(LogHistory.class)
@interface Log {
String date();
String comments();
}
@Log(date = "01/01/2018", comments = "B")
@Log(date = "01/21/2018", comments = "A")
public class Main {
public static void process() {
}
}
本地(Native)注釋型別是元註釋,用於註釋可以從原生代碼參照的欄位。它是一個標記註釋。