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).