複製鏈接
請複製以下鏈接發送給好友

註解

(java註解)

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

註解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:聲明語句、泛型和強制轉換語句中的類型)。還是那句話,這些註解本身是沒有意義的。要靠自己實現類型註解的檢查框架,或者第三方,類型註解最大的意義在於,讓編譯器執行更嚴格的檢查,保證代碼更加的健壯。