java之元數據(metadata)


什么是元數據?

  元數據是指用來描述數據的數據,更通俗一點,就是描述代碼間關系,或者代碼與其他資源(例如數據庫表)之間內在聯系的數據。在一些技術框架,如struts、EJB、hibernate就不知不覺用到了元數據。對struts來說,元數據指的是struts-config.xml;對EJB來說,就是ejb-jar.xml和廠商自定義的xml文件;對hibernate來說就是hbm文件。以上闡述的幾種元數據都是基於xml文件的或者其他形式的單獨配置文件。這樣表示有些不便之處。一、與被描述的文件分離,不利於一致性的維護;第二、所有這樣文件都是ASCII文件,沒有顯式的類型支持。基於元數據的廣泛應用,JDK5.0引入了Annotation的概念來描述元數據。在java中,元數據以標簽的形式存在於java代碼中,元數據標簽的存在並不影響程序代碼的編譯和執行。

如何創建元數據?

  JDK5.0出來后,java語言中就有了四種類型(TYPE),即類(class)、枚舉(enum)、接口(interface)和注解(@interface),它們是處在同一級別的。java就是通過注解來表示元數據的。

      一個簡單的注解定義:

public @interface MyAnnotation {
    // 定義公共的final靜態屬性
    int age = 25;

    // 定義公共的抽象方法
    String name();
}

  反編譯字節碼文件得到:

     

     由上我們可以得到,java的注解本質上是一個接口,而且是繼承了接口Annotation的接口。既然是接口,那么

     a.注解可以有成員
    注解和接口相似,它只能定義final靜態屬性和公共抽象方法。
     b.注解的方法
    1.方法前默認會加上public abstract且只能由這兩個修飾符修飾。屬性前默認加上public static final 且只能由這些修飾符修飾。由於是final,定義時必須初始化。

    2.在聲明方法時可以定義方法的默認返回值。
    例如:
      String color() default "blue";
      String[] color() default {"blue","red",......}
    3.方法的返回值可以有哪些類型
      8種基本類型,String、Class、枚舉、注解及這些類型的數組。

    4.java.lang.annotation.Annotation 本身是接口,而不是注解,當使用關鍵字@interface 定義一個注解時,該注解隱含的繼承了java.lang.annotation.Annotation接口;如果我們定義一個接口,並且讓該接口繼承自Annotation,那么我們定義的接口依然是接口而不是注解。綜上,定義注解只能依靠@interface實現。

JDK提供的幾個基本注解

  a. @SuppressWarnings
      該注解的作用是阻止編譯器發出某些警告信息。
    它可以有以下參數:
      deprecation :過時的類或方法警告。
      unchecked:執行了未檢查的轉換時警告。
      fallthrough:當Switch程序塊直接通往下一種情況而沒有Break時的警告。
      path:在類路徑、源文件路徑等中有不存在的路徑時的警告。
      serial:當在可序列化的類上缺少serialVersionUID定義時的警告。
      finally:任何finally子句不能完成時的警告。
      all:關於以上所有情況的警告。
   b.@Deprecated
    該注解的作用是標記某個過時的類或方法。
   c. @Override
    該注解用在方法前面,用來標識該方法是重寫父類的某個方法。

元注解(注解的注解)

  a. @Retention
   它是被定義在一個注解類的前面,用來說明該注解的生命周期。
   它有以下參數:
      RetentionPolicy.SOURCE:指定注解只保留在源文件當中。
      RetentionPolicy.CLASS:指定注解只保留在class文件中。(缺省)
      RetentionPolicy.RUNTIME:指定注解可以保留在程序運行期間。
   b. @Target
   它是被定義在一個注解類的前面,用來說明該注解可以被聲明在哪些元素前。(默認可以放在任何元素之前)
   它有以下參數:
    ElementType.TYPE:說明該注解只能被聲明在一個類、接口、枚舉前。
    ElementType.FIELD:說明該注解只能被聲明在一個類的字段前。
    ElementType.METHOD:說明該注解只能被聲明在一個類的方法前。
    ElementType.PARAMETER:說明該注解只能被聲明在一個方法參數前。
    ElementType.CONSTRUCTOR:說明該注解只能聲明在一個類的構造方法前。
    ElementType.LOCAL_VARIABLE:說明該注解只能聲明在一個局部變量前。
    ElementType.ANNOTATION_TYPE:說明該注解只能聲明在一個注解類型前。
    ElementType.PACKAGE:說明該注解只能聲明在一個包名前。

  c. @Inherited 表明該注解將會被子類繼承。

     需要說明的是,加上該元注解的注解,只有用在類元素上才有效果。這是在JDK總的原話:

    Note that this meta-annotation type has no effect if the annotated
    type is used to annotate anything other than a class. Note also
    that this meta-annotation only causes annotations to be inherited
    from superclasses; annotations on implemented interfaces have no
    effect

    但是在其他元素上的注解,只要你沒有覆蓋父類中的元素,是會繼承過來的。這就是為什么有getDeclaredAnnotations()和getAnnotations()的原因。

   d. @Documented

    表明在生成JavaDoc文檔時,該注解也會出現在javaDoc文檔中。

注解的生命周期

  一個注解可以有三個生命周期,它默認的生命周期是保留在一個CLASS文件,
   但它也可以由一個@Retetion的元注解指定它的生命周期。
   a.java源文件
      當在一個注解類前定義了一個@Retetion(RetentionPolicy.SOURCE)的注解,那么說明該注解只保留在一個源文件當中,當編譯器將源文件編譯成class文件時,它不會將源文件中定義的注解保留在class文件中。
   b. class文件中
    當在一個注解類前定義了一個@Retetion(RetentionPolicy.CLASS)的注解,那么說明該注解只保留在一個class文件當中,當加載class文件到內存時,虛擬機會將注解去掉,從而在程序中不能訪問。
   c. 程序運行期間
    當在一個注解類前定義了一個@Retetion(RetentionPolicy.RUNTIME)的注解,那么說明該注解在程序運行期間都會存在內存當中。此時,我們可以通過反射來獲得定義在某個類上的所有注解。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM