註解[java註解]

註解[java註解]
註解[java註解]
更多義項 ▼ 收起列表 ▲

從JDK5開始,Java增加對元數據的支持,也就是註解,註解與注釋是有一定區別的,可以把註解理解為代碼里的特殊標記,這些標記可以在編譯,類載入,運行時被讀取,並執行相應的處理。通過註解開發人員可以在不改變原有代碼和邏輯的情況下在原始碼中嵌入補充信息。

1.什麼是註解

註解,可以看作是對 一個 類/方法 的一個擴展的模版,每個 類/方法 按照註解類中的規則,來為 類/方法 註解不同的參數,在用到的地方可以得到不同的 類/方法 中註解的各種參數與值

註解也就是Annotation,相信不少人也和我之前一樣以為和注釋和doc一樣,是一段輔助性的文字,其實註解不是這樣的。

從JDK5開始,java增加了對元數據(描述數據屬性的信息)的支持。其實說白就是代碼里的特殊標誌,這些標誌可以在編譯,類載入,運行時被讀取,並執行相應的處理,以便於其他工具補充信息或者進行部署。

2.基本的Annotation

java提供了5個基本的註解,分別是

1.@Override

2.@Deprecated

3.@SuppressWarnings

4.@SafeVarargs

5.@FunctionalInterface


1.限定父類重寫方法:@Override

當子類重寫父類方法時,子類可以加上這個註解,那這有什麼什麼用?這可以確保子類確實重寫了父類的方法,避免出現低級錯誤

2.標示已過時:@Deprecated

這個註解用於表示某個程式元素類,方法等已過時,當其他程式使用已過時的類,方法時編譯器會給出警告(刪除線,這個見了不少了吧)。

3.抑制編譯器警告:@SuppressWarnings

被該註解修飾的元素以及該元素的所有子元素取消顯示編譯器警告,例如修飾一個類,那他的欄位,方法都是顯示警告

4.“堆污染”警告與@SafeVarargs

想理解這個就要明白什麼是堆污染,堆污染是什麼?

其實很好理解,就是把不帶泛型的對象賦給一個帶泛型的對象,為什麼不行?很簡單,因為不帶泛型的話,默認會給泛型設定為object,意思就是什麼類型都可以往裡面塞,那你一個不帶泛型的怎么可能給一個帶泛型塞呢。

例如運行如下代碼:

List list = new ArrayList(); list.add(20); List<String> ls = list; System.out.println(ls.get(0));則會拋出堆污染異常Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String at Test.Test1.main(Test1.java:29)

注意:可變參數更容易引發堆污染異常,因為java不允許創建泛型數組,可變參數恰恰是數組。
抑制這個警告的方法有三個:

1.@SafeVarargs修飾引發該警告的方法或構造器

2.使用@suppressWarnings("unchecked")

3.編譯時使用-Xlint:varargs

5.函式式接口與@Functionallnterface

什麼是函式式?如果接口中只有一個抽象方法(可以包含多個默認方法或多個static方法)

接口體內只能聲明常量欄位和抽象方法,並且被隱式聲明為public,static,final。

接口裡面不能有私有的方法或變數。

這個註解有什麼用?這個註解保證這個接口只有一個抽象方法,注意這個只能修飾接口

3.自定義註解

定義註解非常的簡單,如下

public @interface Test{}

然後這個註解就可以用在別的地方

例如:

@Test

public class MyClass{}

這個自定義註解可以修飾程式中的類、方法、變數、接口等。通常放在所有修飾符之前。

你還可以為自己的註解類添加成員變數

例如:

public @interface MyTag{

//註解中的成員變數以方法的方式來定義

String name();

int age

}

然後

public class Test{

//當使用自定義註解的時候,這個註解本身是不會生效的,必須由開發者工具提取出來並進行處理。

@MyTag(name = "XX" , age = 6)

public void info(){}

}

你甚至還可以為成員變數指定初始值

public @interface MyTag{

String name() default "yeeku"

int age() default 32;

}

當你指定完默認值的時候,你可以直接@MyTag使用不需要帶參數。

4.JDK的元Annotation

1.使用@Retention

這個註解是用來修飾註解定義的,作用是被修飾的註解可以保存多久,這個註解需要使用參數。

這個參數的類型是RetentionPolicy,所以使用這個註解就要對value賦值。

value的值有且僅有三個:

->RetenionPolicy.CLASS 編譯器把該註解記錄在class檔案中。當運行java程式時,JVM不可獲取註解信息。這是默認值!

->RetenionPolicy.RUNTIME編譯器把該註解記錄在class檔案中。當運行java程式時,JVM可獲取註解信息,程式可以通過反射獲取該註解信息

->RetenionPolicy.SOURCE 該註解只保存在原始碼中,編譯器直接丟棄該註解

例如:@Retention(value =RetenionPolicy.SOURCE) 可簡寫為@Retention(RetenionPolicy.SOURCE)

2.使用@Target

@Target也只能修飾一個註解定義,作用是指定被修飾的註解能用於修飾哪些程式單元,@Target也包含了一個value值,他的值只能是下面的:ElementType.

取值註解使用範圍
METHOD可用於方法上
TYPE可用於類或者接口上
ANNOTATION_TYPE可用於註解類型上(被@interface修飾的類型)
CONSTRUCTOR可用於構造方法上
FIELD可用於域上
LOCAL_VARIABLE可用於局部變數上
PACKAGE用於記錄java檔案的package信息
PARAMETER可用於參數上

例如:

@Target(ElementType.METHOD) (這是簡寫)

public @interface Action()

上面就是他的用法,不過有個比較容易混淆的地方就是@interface和interface不是同一個東西:

@interface 不是interface,是註解類 是jdk1.5之後加入的,java沒有給它新的關鍵字

,所以就用@interface 這么個東西表示了 這個註解類,就是定義一個可用的註解

,包括這個註解用於什麼地方,是類,還是方法,還是property,還是方法入參等等

,還有這個註解是否編譯後進入class 比如我們知道的用於javadoc的註解,是不進入class檔案的。

然後在後面你就可以用這個註解寫代碼了。總的來說,這就是一個生成javadoc時用到的注釋類

3.使用@Documented

這個註解用於指定被修飾的註解類將被javadoc工具提取成文檔,如果定義註解類時使用了這個註解修飾,則所有使用該註解修飾的程式設計師蘇API文檔將會包含該註解說明。

例如:@Documentedpublic @interface Testable{}

4.使用@Inherited

這個註解指定被他修飾的註解將具有繼承性——如果某個類使用了@Xxx,則其子類將自動被@Xxx修飾

5.使用@Result

作用是在同一個程式元素前使用多個相同類型的註解在java8之前只能通過@Results配置,

java8簡化了它的寫法例如:

@test(age=5)@test(age=8)public void resultTest(){}

6.使用類型註解

創建類實例new@InternedMyObject();

類型映射myString = (@NonNullString) str;

implements 語句中class UnmodifiableList<T> implements@ReadonlyList<@Readonly T> { ... }

throw exception聲明void monitorTemperature() throws@CriticalTemperatureException { ... }

等等地方都可以用類型註解

新增ElementType.TYPE_USE和ElementType.TYPE_PARAMETER(在Target上)新增的兩個注釋的程式元素類型 ElementType.TYPE_USE 和 ElementType.TYPE_PARAMETER用來描述註解的新場合。ElementType.TYPE_PARAMETER 表示該註解能寫在類型變數的聲明語句中。

ElementType.TYPE_USE 表示該註解能寫在使用類型的任何語句中(eg:聲明語句、泛型和強制轉換語句中的類型)。還是那句話,這些註解本身是沒有意義的。要靠自己實現類型註解的檢查框架,或者第三方,類型註解最大的意義在於,讓編譯器執行更嚴格的檢查,保證代碼更加的健壯。

相關詞條

熱門詞條

聯絡我們