Java註解

Java 源代码的语法元数据

Java註解又稱Java標註,是Java語言5.0版本開始支援加入原始碼的特殊語法元數據[1]

Java語言中的類、方法、變數、參數和包等都可以被標註。和Javadoc不同,Java標註可以通過反射取得標註內容。在編譯器生成類檔案時,標註可以被嵌入到位元組碼中。Java虛擬機器可以保留標註內容,在執行時可以取得到標註內容[2]。 當然它也支援自訂Java標註[3]

歷史

Java 平台有許多特別的註解,例如 transient 修飾詞,@deprecated javadoc 標籤。2002 年,文案 JSR-175 提出了通用需求的註解(或者說元註解)手段,並在 2004 年 9 月收到許多人的讚賞。[4]從 JDK 1.5 開始,java 開始支援註解。Annotation Processing tool (或者說 apt tool) 提供了一個補充性的編譯時註解操作的介面。文件 JSR-269 將它規範化,在 JDK 1.6 寫入編譯器 javac 中。

內建的註解

Java 定義了一套註解,共有 7 個,3 個在 java.lang 中,剩下 4 個在 java.lang.annotation 中[5][6]

作用在代碼的註解是:

  • @Override - 檢查該方法是否是重寫方法。如果發現其父類別,或者是參照的介面中並沒有該方法時,會報編譯錯誤。
  • @Deprecated - 標記過時方法。如果使用該方法,會報編譯警告。
  • @SuppressWarnings - 指示編譯器去忽略註解中聲明的警告。

作用在其他註解的註解(或者說 元註解)是:

  • @Retention - 標識這個註解怎麼儲存,是只在代碼中,還是編入class檔案中,或者是在執行時可以通過反射訪問。
  • @Documented - 標記這些註解是否包含在用戶文件中。
  • @Target - 標記這個註解應該是哪種 Java 成員。
  • @Inherited - 標記這個註解是繼承於哪個註解類(預設下,註解並沒有繼承於任何子類)

從 Java 7 開始,額外添加了 3 個註解:

  • @SafeVarargs - Java 7 開始支援,忽略任何使用參數為泛型變數的方法或建構函式呼叫產生的警告。
  • @FunctionalInterface - Java 8 開始支援,標識一個匿名函數或函數式介面。
  • @Repeatable - Java 8 開始支援,標識某註解可以在同一個聲明上使用多次。

實例

  // @Twizzle标注toggle()方法。
  @Twizzle
  public void toggle() {
  }

  // 声明Twizzle标注
  public @interface Twizzle {
  }

標註可以包含一個關鍵字和值的對所構成的列表:

  //等同于 @Edible(value = true)
  @Edible(true)
  Item item = new Carrot();

  public @interface Edible {
    boolean value() default false;
  }

  @Author(first = "Oompah", last = "Loompah")
  Book book = new Book();

  public @interface Author {
    String first();
    String last();
  }

標註聲明中可以用標註說明使用方式、時間和對象:

  @Retention(RetentionPolicy.RUNTIME) // 该标注可以在运行时通过反射访问。
  @Target({ElementType.METHOD})       // 该标注只用于类内方法。
  public @interface Tweezable {
  }

編譯器保留一組標註用於特定語法目的 (包括 @Deprecated, @Override@SuppressWarnings等)。

標註通常用於軟件框架為用戶定義的類和方法提供參照外部資源的情形,如XML設定檔、事務環境等。以下是一個標註過的EJB 3.0的類:

  @Entity                                           // 声明实体类
  @Table(name = "people")                           // 映射该类到 "people"表
  class Person implements Serializable {
    @Id                                             // 映射到主键
    @GeneratedValue(strategy = GenerationType.AUTO) // 数据库自动生成键值
    private Integer id;

    @Column(length = 32)                            // 限长32个字符
    private String name;

    public Integer getId() {
      return id;
    }

    public void setId(Integer id) {
      this.id = id;
    }

    public String getName() {
      return name;
    }

    public void setName(String name) {
      this.name = name;
    }
  }

以上代碼中標註不執行任何特定行為,而是為在執行時,EJB容器獲得足夠的資訊,生成對象到關聯式資料庫的對映。

參考參照

  1. ^ JDK 5.0开发者指南:标注. Sun Microsystems. 2007-12-18 [2008-03-05]. (原始內容存檔於2008-03-06). .
  2. ^ Sun Microsystems, Java (TM)语言规范 第三版, Prentice Hall, 2005 [2009-06-14], ISBN 0321246780, (原始內容存檔於2012-02-29) .
  3. ^ Dare Obasanjo. A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE: Metadata Annotations. Dare Obasanjo. 2007 [2012-09-20]. (原始內容存檔於2012-09-19). 
  4. ^ Coward, Danny. JSR 175: A Metadata Facility for the JavaTM Programming Language. Java Community Process. 2006-11-02 [2008-03-05]. (原始內容存檔於2011-03-06). 
  5. ^ Predefined Annotation Types. Oracle Corporation. [2016-12-17]. (原始內容存檔於2020-12-23). 
  6. ^ The Built-In Annotations : Standard Annotations. [2016-12-17]. (原始內容存檔於2021-01-10).