大家好,我是樂位元組的小樂,上次說過了Java多型的6大特性|樂位元組,接下來我們來看看Java程式設計裡的註解。
Java註解有以下幾個知識點:
- 後設資料
- 註解的分類
- 內建註解
- 自定義註解
- 註解處理器
- Servlet3.0
本文先介紹前面4個知識點:後設資料、註解的分類、內建註解、自定義註解。
一、註解簡介
註解是Java 1.5引入的,目前已被廣泛應用於各種Java框架,如Hibernate,Jersey,
Spring。註解相當於是一種嵌入在程式中的後設資料,可以使用註解解析工具或編譯器對
其進行解析,也可以指定註解在編譯期或執行期有效。
在註解誕生之前,程式的後設資料存在的形式僅限於java註釋或javadoc,但註解可以提
供更多功能,它不僅包含後設資料,還能作用於執行期,註解解析器能夠使用註解決定處
理流程。
Annotation(註解)就是Java提供了一種元程式中的元素關聯任何資訊和任何後設資料
(metadata)的途徑和方法。Annotation是一個介面,程式可以通過反射來獲取指定
程式元素的Annotation物件,然後通過Annotation物件來獲取註解裡面的後設資料。
註解API非常強大,被廣泛應用於各種Java框架,如Spring,Hibernate,JUnit。
二、 後設資料metadata
後設資料從metadata一詞譯來,就是“關於資料的資料”的意思,即描述資料的結構資訊。後設資料的功能作用有很多,比如:你可能用過Javadoc的註釋自動生成文件。這就是後設資料功能的一種。總的來說,後設資料可以用來建立文件,跟蹤程式碼的依賴性,執行編譯時格式檢查,代替已有的配置檔案。
在Java中後設資料以標籤的形式存在於Java程式碼中,後設資料標籤的存在並不影響程式程式碼的編譯和執行,被用來生成其它的檔案或只在執行時知道被執行程式碼的描述資訊。
其作用如下:
①生成文件:這是最常見的,也是java 最早提供的註解。常用的有@param @return 等;
② 跟蹤程式碼依賴性,實現替代配置檔案功能。常見的是spring 2.5 開始的基於註解配置。作用就是減少配置。現在的框架基本都使用了這種配置來減少配置檔案的數量。;
③在編譯時進行格式檢查。如@override 放在方法前,如果你這個方法並不是覆蓋了超類方法,則編譯時就能檢查出。
三、 註解的分類
根據註解引數的個數:
1)、標記註解:一個沒有成員定義的Annotation型別被稱為標記註解。
2)、單值註解:只有一個值
3)、完整註解:擁有多個值
根據註解使用方法和用途:
1)、JDK內建系統註解
2)、元註解
3)、自定義註解
四、 內建註解
JavaSE中內建三個標準註解,定義在java.lang中:
@Override
限定重寫父類方法,若想要重寫父類的一個方法時,需要使用該註解告知編譯器我們正在重寫一個方法。如此一來,當父類的方法被刪除或修改了,編譯器會提示錯誤資訊;或者該方法不是重寫也會提示錯誤。
public interface Car {
void run();
}
class QQ implements Car{
@Override
public void run() {}
}
class Bmw implements Car{
@Override
void run() {}
}複製程式碼
QQ 類編譯不會有任何問題,Bmw類在編譯的時候會提示相應的錯誤。父類中省略了public abstract修飾符。@Override註解只能用於方法,不能用於其他程式元素。
@Deprecated
標記已過時,當我們想要讓編譯器知道一個方法已經被棄用(deprecate)時,應該使用這個註解。Java推薦在javadoc中提供資訊,告知使用者為什麼這個方法被棄用了,以及替代方法是什麼;
/**
* Deprecated -->該方法過時(有更好的解決方案)
* @author Administrator
*/
public class TestDeprecated {
@Deprecated
public int test(){
System.out.println("TestDeprecated.test()");
return 0;
}
public void test(int a){
System.out.println("TestDeprecated.test(int)");
}
}複製程式碼
3. @SuppressWarnings
抑制編譯器警告,該註解僅僅告知編譯器,忽略它們產生了特殊警告。如:在java泛型中使用原始型別。其保持性策略(retention policy)是SOURCE,在編譯器中將被丟棄。
/**
* SuppressWarnings 壓制警告
* @author Administrator
*/
public class TestSuppressWarnings {
public static void main(String[] args) {
@SuppressWarnings("unused")
List<String> list =new ArrayList<String>();
}
@SuppressWarnings("rawtypes") //沒有定義範型
public static List test(){
return new ArrayList();
}
}複製程式碼
五、 自定義註解
1、簡單入門
@interface:用來宣告一個註解。註解類裡的每一個方法實際上是宣告瞭一個配置引數。方法的名稱就是引數的名稱,返回值型別就是引數的型別。可以通過default來宣告引數的預設值。
@interface Simple{
//這裡定義了一個空的註解,它能幹什麼呢?我也不知道,但他能用。後面有補充
}複製程式碼
2、元註解
元註解的作用就是負責註解其他註解。Java5.0定義了4個標準的meta-annotation型別,它們被用來提供對其它 annotation型別作說明。Java5.0定義的元註解有四個,
這些型別和它們所支援的類在java.lang.annotation包中可以找到。
@Target
用於描述註解的使用範圍(即:被描述的註解可以用在什麼地方)。表示支援註解的程式元素的種類,一些可能的值有TYPE, METHOD, CONSTRUCTOR, FIELD等等。如果Target元註解不存在,那麼該註解就可以使用在任何程式元素之上。
取值(ElementType)有:
1.CONSTRUCTOR:用於描述構造器
2.FIELD:用於描述域
3.LOCAL_VARIABLE:用於描述區域性變數
4.METHOD:用於描述方法
5.PACKAGE:用於描述包
6.PARAMETER:用於描述引數
7.TYPE:用於描述類、介面(包括註解型別) 或enum宣告
此時在空註解中加入@Target元註解如:
//此註解只能用在方法上
@Target(ElementType.METHOD)
@interface TestMethod {}複製程式碼
@Retention
表示需要在什麼級別儲存該註釋資訊,用於描述註解的生命週期(即:被描述的注解在什麼範圍內有效)表示註解型別保留時間的長短。
取值(RetentionPoicy)有:
1.SOURCE:在原始檔中有效(即原始檔保留)
2.CLASS:在class檔案中有效(即class保留)
3.RUNTIME:在執行時有效(即執行時保留)
此時在上述註解中加入@Retention元註解如:
// 此註解可以用於註解類、介面(包括註解型別) 或enum宣告
@Target(ElementType.TYPE)
//該註解執行時有效。註解處理器可以通過反射,獲取到該註解的屬性值,從而去做一些執行時的邏輯處理
@Retention(RetentionPolicy.RUNTIME)
@interface TestRn{
}複製程式碼
@Documented
表示使用該註解的元素應被javadoc或類似工具文件化,它應用於型別宣告,型別宣告的註解會影響客戶端對註解元素的使用。如果一個型別宣告新增了Documented註解,那麼它的註解會成為被註解元素的公共API的一部分,@Documented是一個標記註解。
//可以被例如javadoc此類的工具文件化
@Documented
@interface TestDoc{
}複製程式碼
@Inherited
表示一個註解型別會被自動繼承,如果使用者在類宣告的時候查詢註解型別,同時類宣告中也沒有這個型別的註解,那麼註解型別會自動查詢該類的父類,這個過程將會不停地重複,直到該型別的註解被找到為止,或是到達類結構的頂層(Object)。
//被子類繼承的註解
@Inherited
@interface TestInheri{}複製程式碼
3、深入自定義註解
使用@interface自定義註解時,自動繼承了java.lang.annotation.Annotation介面,由編譯程式自動完成其他細節。在定義註解時,不能繼承其他的註解或介面。
⑴定義註解格式:
@interface用來宣告一個註解,其中的每一個方法實際上是宣告瞭一個配置引數。方法的名稱就是引數的名稱,返回值型別就是引數的型別(返回值型別只能是基本型別、Class、String、enum)。可以通過default來宣告引數的預設值。
public @interface 註解名{定義體s}
⑵註解引數(即方法)
註解裡面的每一個方法實際上就是宣告瞭一個配置引數,其規則如下:
①修飾符
只能用public或預設(default)這兩個訪問權修飾 ,預設為default
②型別
註解引數只支援以下資料型別:
基本資料型別(int,float,boolean,byte,double,char,long,short);
String型別;
Class型別;
enum型別;
Annotation型別;
以上所有型別的陣列
③命名
對取名沒有要求,如果只有一個引數成員,最好把引數名稱設為"value",後加小括號。
④引數
註解中的方法不能存在引數
⑤預設值
可以包含預設值,使用default來宣告預設值。
⑶例項如下
/*
* 碼農定義註解
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface Programmer{
String value() default "馬雲";
}
/**
* 碼農型別註解
* @author peida
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface ProgrammerType {
/**
* 型別列舉 程式猿 射雞師
*/
public enum CoderType{MONKEYS,LION,CHOOK};
/**
* 顏色屬性
*/
CoderType type() default CoderType.MONKEYS;
}
/**
* 碼農製造廠
* @author Administrator
*/
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface ProgrammerProductor {
/**
* 廠家編號
* @return
*/
public int id() default -1;
/**
* 廠家名稱
* @return
*/
public String name() default "shsxt";
/**
* 廠家地址
* @return
*/
public String address() default "上海";
}
/**
* 註解使用
*/
class Coder{
@Programmer("老裴")
private String coderName;
@ProgrammerType(type=CoderType.MONKEYS)
private String coderType;
@ProgrammerProductor(id=1,name="程式猿樂園",address="榮樂東路")
private String coderProductor;
public String getCoderName() {
return coderName;
}
public void setCoderName(String coderName) {
this.coderName = coderName;
}
public String getCoderType() {
return coderType;
}
public void setCoderType(String coderType) {
this.coderType = coderType;
}
public String getCoderProductor() {
return coderProductor;
}
public void setCoderProductor(String coderProductor) {
this.coderProductor = coderProductor;
}
}
樂位元組原創,轉載請註明出處複製程式碼