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.自定義註解

1.定義註解非常的簡單,如下
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文檔將會包含該註解說明。
例如:
@Documented
public @interface Testable{}
4.使用@Inherited
這個註解指定被他修飾的註解將具有繼承性——如果某個類使用了@Xxx,則其子類將自動被@Xxx修飾
5.使用@Result
作用是在同一個程序元素前使用多個相同類型的註解
在java8之前只能通過@Results配置,java8簡化了它的寫法
例如:
@test(age=5)
@test(age=8)
public void resultTest(){}
6.使用類型註解
讓我們先看幾個例子:
  • 創建類實例
new@Interned MyObject();
  • 類型映射
myString = (@NonNull String) str;
  • implements 語句中
class UnmodifiableList<T> implements@Readonly List<@Readonly T> { ... }
  • throw exception聲明
void monitorTemperature() throws@Critical TemperatureException { ... }
等等地方都可以用類型註解

新增ElementType.TYPE_USE 和ElementType.TYPE_PARAMETER(在Target上

新增的兩個註釋的程序元素類型 ElementType.TYPE_USE 和 ElementType.TYPE_PARAMETER用來描述註解的新場合 ElementType.TYPE_PARAMETER 表示該註解能寫在類型變量的聲明語句中。 ElementType.TYPE_USE 表示該註解能寫在使用類型的任何語句中(eg:聲明語句、泛型和強制轉換語句中的類型)。
還是那句話,這些註解本身是沒有意義的。要靠自己實現類型註解的檢查框架,或者第三方,類型註解最大的意義在於,讓編譯器執行更嚴格的檢查,保證代碼更加的健壯。
發佈了30 篇原創文章 · 獲贊 9 · 訪問量 6086
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章