剎那間我真想令時光停住,好讓我回顧自己,回顧失去的年華,緬懷哪個穿一身短小的連衣裙
和瘦窄的短衫的小女孩。讓我追悔少年時代,我心靈的愚鈍無知,它輕易地錯過了我一生中本來
可以獲得歡樂和幸福。
—————— 《平凡的世界》
真的,如果痛苦不能改變生存,那還不如平靜地將自己毀滅,毀滅,一切都毀滅了,
只有生命還在苟延殘喘,這樣的生命還有有什麼存在的價值。
—————— 《平凡的世界》
@
註解,一種後設資料形式提供了一個不屬於程式本身的程式的資料。註解對他們註解的程式碼的操作沒有直接的影響。
註解有很多用途,其中:
從 JDK5.0 開始,Java增加了對後設資料(MetaData) 的支援,也就是 Annotation 註解。
程式設計師可以在不改變原有的邏輯的情況下,在原始檔種嵌入一些補充的資訊。程式碼分析工具,開發工具和部署工具可以通過這些補充資訊進行驗證或進行部署。
註解: 可以像修飾符一樣被使用,可以用於 修飾:包,類,構造器,方法,成員變數,引數,區域性變數的宣告 。這些資訊被儲存在 註解 Annotaion 的「 name = value」 鍵值對中。
在JavaSE中,註解的使用目的比較簡單,例如標記過時的功能,忽略警告等。在JavaEE/Android中註解佔據了更重要的角色,例如
用來設定應用程式的任何切面,代替JavaEE舊版中所遺留的繁冗 程式碼和XML設定等。
未來的開發模式都是基於註解的,JPA 是基於註解的,Spring2.5 以上都是基於註解的,Hibernate3.x 以後也是基於註解的,
現在Struts2 有一部分也是基於註解的了。註解是一種趨勢,一定程度上可以說:框架 = 註解 + 反射 + 設計模式 。
從 JVM 的角度看,註解本身對程式碼邏輯沒有任何影響,如何使用註解完全由工具決定。
Java的註解可以分為三類:
.class
檔案使用的註解,比如有些工具會在載入 class 的時候,對 class 做動態修改,實現一些特殊的功能。這類註解會被編譯進入到 .class
檔案,但載入結束後並不會存在於記憶體中。這類註解只被一些底層使用,一般我們不必自己處理。@PostConstruct
的方法會在呼叫構造方法後自動被呼叫,(這是Java程式碼讀取該註解實現的功能,JVM 並不會識別該註解)。Annotaion註解 其實也是一種參照資料型別,編譯之後也是生成 xxx.class
位元組碼檔案的。
定義新的 Annotation 註解 型別使用 @interface 關鍵字
自定義註解自動實現了 java.lang.annotation.Annotation
介面
自定義註解的格式如下:
public @interface MyAnnotation {
}
//
[修飾列表] @interface 註解名/(註解類名) {
}
使用 IDEA 建立一個 註解型別: 滑鼠右鍵 ——> new 一個選擇 :
如下檢視該 我們該自定義的註解 MyAnnotation 的 UML 圖:可以清楚的看到該 註解型別是自動繼承了該 java.lang.annotation.Annotation
介面的
但是事實上卻是自動實現了 java.lang.annotation.Annotation
介面。
在Java 8之前,註解只能是在宣告的地方所使用,Java8 開始,註解可以應用 在任何地方 。這裡的任何地方包括:包,類,構造器,方法,成員變數,引數,區域性變數的宣告 。這些資訊被儲存在 註解 Annotaion 的「 name = value」 鍵值對中。
舉例如下: 並沒有出現任何的報錯的情況。
在註解中可以定義屬性。
Java中的註解中的屬性:看著像方法,但實際在註解當中是屬性 name
格式如下:
String value();
// 資料型別 屬性名(); // 看似是方法,其實在註解中是屬性
註解中的屬性可以是任何型別:byte, short, int, long, float, double, boolean, char, String, long, Class, 列舉型別
。再或者是自定義型別。
舉例:
public @interface MyAnnotation {
String value();
}
注意: 如果該註解中定義了屬性,則宣告使用該註解時 必須 為其註解中的屬性值賦上值,不然,是會報錯的。
如下,我們為該 @MyAnnotation
註解定義了屬性,使用時卻沒有賦值,報如下編譯錯誤。
為註解中的屬性賦值的格式如下:
@MyAnnotaion(value="Tom") // 注意:在該註解中定義的是什麼型別的值,就賦值對應的值,不然會報錯的
// @註解名(註解中的屬性名=對應賦值的屬性值)
舉例:
如果該註解中只有一個屬性值,並且該註解的屬性名為 value
,則在賦值時,可以省略其 為value的屬性名,直接寫值 。
注意一定要滿足兩個條件:1. 該註解中只有一個屬性值,2.該屬性名為 value
舉例:
為註解中的多個屬性賦值格式如下: 多個屬性值,使用逗號分隔開來,就可以了。
@MyAnnotation(value = "Tom",value2 = "123")
// @註解名(註解中的屬性名=值,註解中的屬性名=值) :多個屬性值使用逗號分隔開。
注意: 當註解中存在多個屬性值時,其中所有該註解中的屬性值都必須賦值,不然編譯報錯,如下:
必須將註解中的所有屬性值都賦值上值才行:如下:如果註解中存在兩個或兩個以上的屬性,就算其中存在一個屬性名為 value
,其賦值時,該value 屬性名是不可以省略的。必須寫明所有的屬性名的進行賦值。[外連圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳
註解中的屬性可以設定預設值,使用關鍵字``格式如下:
String value() default "Tom";
// 資料型別 屬性名() default 預設值; 注意需要和定義的型別保證一致。
舉例:
public @interface MyAnnotation {
String value() default "Tom";
}
註解中屬性設定了,預設值的是可以選擇不進行賦值操作,使用定義的預設值。
舉例如下:
註解中的屬性值是可以定義為陣列屬性的格式如下:
String[] arr(); // 定義陣列為屬性值
資料型別[] 屬性名();
舉例:
public @interface MyAnnotation {
String value();
String[] arr();
}
註解中以陣列為屬性的賦值格式如下:
@MyAnnotation(value = "Tom",arr = {"hello","world"})
@註解名(屬性名=值,屬性名={值,值})
舉例:
當陣列屬性所賦值的引數只有一個時,可以省略{}
花括號。如下
下面我們來認識一下,JDK 中三個常見的基本註解。
@Override : 的作用就是在編譯期間:讓編譯器檢查該方法是否正確的實現了 重寫 操作。其中的重寫的方法名是否存在錯誤,方法的返回值型別是否是父類別中/介面中的一致。不一致編譯報錯,提示我們改正。
@OVerride 註解的原始碼,可以看到該註解是沒有定義屬性的。
package java.lang;
import java.lang.annotation.*;
/**
* Indicates that a method declaration is intended to override a
* method declaration in a supertype. If a method is annotated with
* this annotation type compilers are required to generate an error
* message unless at least one of the following conditions hold:
*
* <ul><li>
* The method does override or implement a method declared in a
* supertype.
* </li><li>
* The method has a signature that is override-equivalent to that of
* any public method declared in {@linkplain Object}.
* </li></ul>
*
* @author Peter von der Ahé
* @author Joshua Bloch
* @jls 9.6.1.4 @Override
* @since 1.5
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}
注意 : 該註解只能使用在方法上(因為該註解的原始碼中被@Target(ElementType.METHOD)
元註解修飾了),在其他位置上是會編譯報錯的。如下:
@OVerride 註解的使用: 較少了我們程式設計程式時,上的簡單符號上以及一些基本的語法錯誤。
@Deprecated : 該註解表示:表示所修飾的元素(類,方法等)已過時了,不建議使用它了。建議替換成其他的方法。
@Depecated 原始碼: 可以看到該註解是沒有定義屬性的。
package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
/**
* A program element annotated @Deprecated is one that programmers
* are discouraged from using, typically because it is dangerous,
* or because a better alternative exists. Compilers warn when a
* deprecated program element is used or overridden in non-deprecated code.
*
* @author Neal Gafter
* @since 1.5
* @jls 9.6.3.6 @Deprecated
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(value={CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public @interface Deprecated {
}
常見的,在我們的 java.util.lang
包下的 Date 中的 Date(String s) 構造器是被 @Deprecated 註解修飾了的。
在IDEA 中 如果我們呼叫了,被 @Deprecated 修飾的屬性,方法,構造器,會給一個直觀的將該屬性/方法以刪除線的方式顯示處理
並提示你建議使用別的方式替換 。如下
我們也可以自己寫一個這樣的被@Deprecated 修飾的屬性/方法/類/構造器。舉例如下:
@SuppressWarnings ** :指示應該在註解元素(以及包含在該註解元素中所有程式元素中的所有程式元素)中取消顯示指定的編譯器警告。換句話說:就是告訴編譯器忽略此處程式碼產生的警告**。 注意是警告不是異常。
@SuppressWarnings的原始碼 ,可以看到該註解定義了一個名為 value
的屬性。
package java.lang;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
/**
* Indicates that the named compiler warnings should be suppressed in the
* annotated element (and in all program elements contained in the annotated
* element). Note that the set of warnings suppressed in a given element is
* a superset of the warnings suppressed in all containing elements. For
* example, if you annotate a class to suppress one warning and annotate a
* method to suppress another, both warnings will be suppressed in the method.
*
* <p>As a matter of style, programmers should always use this annotation
* on the most deeply nested element where it is effective. If you want to
* suppress a warning in a particular method, you should annotate that
* method rather than its class.
*
* @author Josh Bloch
* @since 1.5
* @jls 4.8 Raw Types
* @jls 4.12.2 Variables of Reference Type
* @jls 5.1.9 Unchecked Conversion
* @jls 5.5.2 Checked Casts and Unchecked Casts
* @jls 9.6.3.5 @SuppressWarnings
*/
@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE)
public @interface SuppressWarnings {
/**
* The set of warnings that are to be suppressed by the compiler in the
* annotated element. Duplicate names are permitted. The second and
* successive occurrences of a name are ignored. The presence of
* unrecognized warning names is <i>not</i> an error: Compilers must
* ignore any warning names they do not recognize. They are, however,
* free to emit a warning if an annotation contains an unrecognized
* warning name.
*
* <p> The string {@code "unchecked"} is used to suppress
* unchecked warnings. Compiler vendors should document the
* additional warning names they support in conjunction with this
* annotation type. They are encouraged to cooperate to ensure
* that the same names work across multiple compilers.
* @return the set of warnings to be suppressed
*/
String[] value();
}
舉例: 這裡我們定義一個 int num = 1 / 0 語句,IDEA 該我們提示了警告了。
當我們加上了 @SuppressWarnings IDEA 就沒有這個警告了。如下:
具體的其他應用大家可以移步至: