Java 註解 So Easy!!!

Java註解

Annotations, a form of metadata, provide data about a program that is not part of the program itself. Annotations have no direct effect on the operation of the code they annotate.
Java
註解是一種元數據,(元數據,用來描述數據的數據,主要其描述作用,讓數據變得有具體的作用),註解對程序提供一些數據,但不是程序的部分.註解不能直接影響所標註的代碼. 

註解用於爲 Java 代碼提供元數據。作爲元數據,註解不直接影響你的代碼執行,但也有一些類型的註解實際上可以用於這一目的。Java 註解是從 Java5 開始添加到 Java 的。

註解有許多用處,主要如下:

提供信息給編譯器(Information for the compiler): 編譯器可以利用註解來探測錯誤和警告信息
編譯階段時的處理(Compile-time and deployment-time processing ): 軟件工具可以用來利用註解信息來生成代碼、Html文檔或者做其它相應處理。
運行時的處理(Runtime processing): 某些註解可以在程序運行的時候被檢測到 
值得注意的是,註解不是代碼本身的一部分。

一. 註解的基礎

利用IDE自動生成重寫父類或者接口的方法時,都會生成如下的格式:

@Override
void mySuperMethod() { ... }

其中@Override就是一個簡單的註解 @暗示編譯器這是一個註解.
同樣註釋也可以擁有屬性,例如:

@Author(
   name = "Benjamin Franklin",
   date = "3/27/2003"
)
class MyClass() { ... }

如果只有一個屬性,可以省略=和屬性名

@SuppressWarnings(value = "unchecked")
void myMethod() { ... }
//等效的
@SuppressWarnings("unchecked")
void myMethod() { ... }

如果註解沒有屬性,那麼括號也可以省略

@Author(name = "Jane Doe")
@Author(name = "John Smith")
@EBook
class MyClass { ... }

細心的讀者可能發現.這裏使用了兩個@Author.通常註解只能是一個,在JKD1.8出現了可重複註解

在哪裏使用註解 :
在JDK 1.8之前, 註解只能使用在聲明地方,例如類的聲明,方法的聲明,屬性的聲明的地方.通常的約定是註解獨佔一行.在JDK 1.8之後,註解可以出現在使用類型的地方

  • 創建一個對象時:
    new @Interned MyObject();
    
  • 類型轉換
  myString = (@NonNull String) str;
  • 拋出異常時:
    void monitorTemperature() throws
        @Critical TemperatureException { ... }

上面的這種用法叫做類型註解,可以在任何使用類型的地方使用.類型可以包括(類,屬性,方法,定義的常量).這是JDK 1.8 更新的內容,同時更新的還有可重複註解

二.如何創建一個註解

註解通過 @interface 關鍵字進行定義。它的形式跟接口很類似,不過前面多了一個 @ 符號。上面的代碼就創建了一個名字爲 TestAnnotaion 的註解。

public @interface TestAnnotation {
}

使用自定義註解

@TestAnnotation
public class Test {
}

創建帶有屬性的註解

@interface ClassPreamble {
   String author();
   String date();
   int currentRevision() default 1;
   String lastModified() default "N/A";
   String lastModifiedBy() default "N/A";
   // Note use of array
    //在這裏使用了數組作爲屬性
   String[] reviewers();
}
@ClassPreamble (
   author = "John Doe",
   date = "3/17/2002",
   currentRevision = 6,
   lastModified = "4/12/2004",
   lastModifiedBy = "Jane Doe",
   // Note array notation
   //數組在註解的使用方法
   reviewers = {"Alice", "Bob", "Cindy"}
)
public class Generation3List extends Generation2List {
// class code goes here
}

三.可重複的註解:

這是JDK1.8 的更新.
例如:
如果你寫了一個方法,需要在不同的時間執行,例如像UNIX的定時任務.那麼我們可以利用註解@Schedule來表明方法執行的會時間 .

@Schedule(dayOfMonth="last")
@Schedule(dayOfWeek="Fri", hour="23")
public void doPeriodicCleanup() { ... }

它的創建需要兩個部分

  • 定義一個可以重複的註解
import java.lang.annotation.Repeatable;

@Repeatable(Schedules.class) //不要忘記.class
public @interface Schedule {
  String dayOfMonth() default "first";
  String dayOfWeek() default "Mon";
  int hour() default 12;
}
  • 聲明一個重複註解類型的容器
public @interface Schedules {
    Schedule[] value();
}

什麼是容器註解呢?就是用來存放其它註解的地方。它本身也是一個註解。 按照規定,它裏面必須該容器要有一個 value 的屬性,屬性類型是一個被 @Repeatable 註解過的註解數組,注意它是數組。

四. Java語言預定義的註解(Predefined Annotation Types

在Java API中提前 定義了一些註解,這些註解有的被編譯器使用(例如@Overrider),有的被其他註解使用 ,被其他註解使用的有 @Retention @Document @Target @Inherited @Repeatable5種

@Retention

@Retention 應用到一個註解上的時候,它解釋說明了這個註解的的生命週期。
它的取值如下:

  • RetentionPolicy.SOURCE : 註解只在源代碼階段保留,在編譯器編譯時將忽略它
  • RetentionPolicy.CLASS : 註解只在編譯階段存在,不會加載到JVM中
  • RetentionPolicy.RUNTIME :註解可以保留到程序運行,在程序運行時可以獲取到他們
  1. @DOCument
    這個註解表示能夠將註解中的元素包含到Javadoc中.
  2. @Target
    @Target 表示註解運用的地方 ,限定註解使用的地方
  • ElementType.ANNOATION_TYPE 可以給一個註解 進行註解
  • ElementType.CONSTRUCTOR 可以給構造器註解
  • ElementType.FIELD 可以給豎向進行註解
  • ElementType.LOCAL_VARIABLE 可以給局部局部變量註解
  • ElementType.METHOD 可以給方法註解
  • ElemntType.PACKAGE 可以給包註解
  • ElementType.PARMETER 可以給一個方法內的參數進行註解
  • ElementType.TYPE 可以給一個類型進行註解,比如類,接口,枚舉
  1. @Inherited
    Inherited 是繼承的意思,但是它並不是說註解本身可以繼承,而是說如果一個超類被 @Inherited 註解過的註解進行註解的話,那麼如果它的子類沒有被任何註解應用的話,那麼這個子類就繼承了父類的註解。

五 類型註解

Java8 爲 ElementType 枚舉增加了TYPE_PARAMETER、TYPE_USE兩個枚舉值,從而可以使用 @Target(ElementType_TYPE_USE) 修飾註解定義,這種註解被稱爲類型註解,可以用在任何使用到類型的地方。
在 java8 以前,註解只能用在各種程序元素(定義類、定義接口、定義方法、定義成員變量…)上。從 java8 開始,類型註解可以用在任何使用到類型的地方。

TYPE_PARAMETER:表示該註解能寫在類型參數的聲明語句中。 類型參數聲明如: 、
TYPE_USE:表示註解可以再任何用到類型的地方使用,比如允許在如下位置使用:

  • 創建對象(用 new 關鍵字創建)
  • 類型轉換
  • 使用 implements 實現接口
  • 使用 throws 聲明拋出異常
@Target(ElementType.TYPE_USE)
@interface NotNull{

}

// 定義類時使用
// 在implements時使用
@NotNull
public class TypeAnnotationTest implements Serializable {

    // 在方法形參中使用
    // 在throws時使用
    public static void main(@NotNull String [] args) throws @NotNull FileNotFoundException {

        Object  obj = "fkjava.org";

        // 使用強制類型轉換時使用
        String str = (@NotNull String) obj;

        // 創建對象時使用
        Object win = new (@NotNull) JFrame("瘋狂軟件");   
    } 

    // 泛型中使用
    public void foo(List<@NotNull String> info) {

    }
}

這種類型註解,可以讓編譯器執行更嚴格的代碼檢查,從而提高程序的健壯性。
java8本身並沒有提供這種註解的框架,要想這些註解發揮作用,需要開發者自己實現,或者使用第三方提供的工具
這裏提供一個第三方框架 Checker Framework,如果感興趣的話可以看一看.

參考

The Java™ Tutorials
JDK 8 新特性 | 重複註解與類型註解

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章