Java註解型別


標記註解型別

標記註解型別是沒有元素的註解型別,甚至沒有預設值。標記註解由註解處理工具使用。

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)注釋設定注釋型別的保留策略。注釋可以在三個級別保留 -

  • 僅原始碼
  • 僅類檔案,預設行為。
  • 類檔案和執行時

保留(Retention)元註釋型別指定Java應如何保留註釋。如果注釋型別具有「僅限原始碼」保留策略,則在編譯到類檔案中時將刪除其範例。如果保留策略為「僅類檔案」,則其範例將保留在類檔案中,但不能在執行時讀取。
如果保留策略為「類檔案和執行時」,則注釋範例保留在類檔案中,並且它們可在執行時讀取。保留元註釋型別宣告一個名為value的元素,它是java.lang.annotation.RetentionPolicy列舉型別。

RetentionPolicy列舉有三個常數:SOURCECLASSRUNTIME,它們分別用於指定僅源,僅類和類執行時的保留策略。

以下程式碼在版本註釋型別上使用保留元注釋。它指定版本註釋應該在執行時可用。

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)注釋型別是元註釋,用於註釋可以從原生代碼參照的欄位。它是一個標記註釋。