亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

Java注釋Annotation

Java注釋Annotation

幕大哥 2014-10-27 16:09:42
Java注釋Annotation從JDK 5開始,Java增加了對元數據(MetaData)的支持,也就是Annotation(注釋)。Annotation提供了一種為程序元素設置元數據的方法,程序元素包括修飾包、類、構造器、方法、成員變量、參數、局部變量,從某些方面來看,Annotation就想修飾符一樣,可用于程序元素的聲明,這些信息被存儲在Annotation的”name = value”對中。需要注意的是, Annotation是一個接口,程序可以通過反射來獲取指定程序元素的Annotation對象,然后通過Annotation對象來取得注釋里的元數據,且不會影響程序代碼的執行,無論增加、刪除Annotation,代碼都始終如一地執行。如果希望讓程序中的Annotation在運行時起一定的作用,只有通過某種配套的工具對Annotation中的信息進行訪問和處理,訪問和處理Annotation的工具統稱為APT(Annotation ProcessingTool)。?一、Annotation基礎前面已經講到APT負責提取Annotation里包含的元數據,那么我們先了解一下4個基本Annotation的使用,需要在Annotation前面加上@符號,以修飾符的形式放在程序元素的前面。4個基本的Annotation如下:@Override@Deprecated@SuppressWarnings@SafeVarargs1、@Override——限定重寫父類方法顧名思義,@Override就是用來重寫方法的,它只能作用于方法,不能作用于其他程序元素,它可以強制一個子類必須覆蓋父類的方法。通常情況下會被省略,例如下面的程序指定了子類Circle的draw()方法必須重寫父類方法:class?Shape{???void?draw(){??????System.out.println("畫一個形狀");???}}class?Circle?extends?Shape{???//將@Override省略效果相同???@Override???void?draw() {??????System.out.println("畫一個圓形");???}}但是@Override作為一個標識,可以告訴我們該方法在其父類中是不是存在,或者我們需要重寫的方法是否跟父類中的方法一致,例如上面的程序,如果我把draw()寫成darw(),系統將會報編譯錯誤。?2、@Deprecated——標示已過時用于表示某個程序元素(類、方法等)已過時,當其他程序使用已過時的類、方法時,編譯器將會給出警告。例如:public?classTest{???public?static?void?main(String[] args) {??????//下面調用shape的draw方法時,編譯器會給出警告??????new?Shape().draw();???}}?class?Shape{???@Deprecated???void?draw(){??????System.out.println("畫一個形狀");???}}?3、@supressWarnings——抑制編譯器警告指示被該Annotation修飾的程序元素(以及該程序元素中的所有子元素)取消顯示指定的編譯器警告。@SupressWarnings會抑制作用于該程序元素的所有子元素,例如,使用@SupressWarnings修飾某個類取消顯示某個編譯器警告,同時又修飾該類里的某個方法取消顯示另一個編譯器警告,那么該方法將會同時取消顯示這兩個編譯器警告。在通常情況下,如果程序中使用沒有泛型限制的集合,將會引起編譯器的警告,為了避免編譯器的警告,可以使用@SupressWarnings修飾,例如://關閉整個類里的編譯器警告@SuppressWarnings("unchecked")public?class?Test{???public?static?void?main(String[]args) {??????List<String>?tempList?=?new?ArrayList();???}}?4、Java7的“堆污染”警告與@SafeVarargs要理解堆污染,首先看一個例子:?????List list =?new?ArrayList<Integer>();??????list.add(10);//添加元素時引發unchecked異常??????//下面代碼引起“未經檢查的轉換”的警告,但編譯、運行時完全正常??????List<String> temp = list;??????//但只要訪問temp里的元素,就會引起運行時異常??????System.out.println(temp.get(0));如上所示,將list賦值給temp就造成了所謂的“堆污染”當把一個不帶泛型的對象賦值給一個帶泛型的變量時,往往就會引發“堆污染”。對于形參個數可變的方法,如果該形參的類型是泛型,就更容易引發“堆污染”了,例如下面的方法中,相當于把List<String>賦值給了List。該方法首先將listArray與listStrArray指向同一內存地址,然后將整型集合賦值給listArray的第一個元素,再使用listStrArray取出第一個元素時,將引發ClassCastException異常:??public?voidtemp(List<String>... listStrArray){??????List[] listArray = listStrArray;??????List<Integer> tempList = Arrays.asList(99);??????listArray[0] = tempList;??????String s = listStrArray[0].get(0);}而我們這里要講的@SafeVarargs,就是Java7專門用來一直“堆污染”警告而提供的Annotation。除此之外,另一種方法就是我們上面所將的,使用@SuppressWarning(“unchecked”)修飾。?二、JDK的元Annotation你可能會覺得這4個Annotation使用起來不太方便,認為Annotation只有這么幾個功能。其實,這只是Annotation的鳳毛麟角,如果我們想深入了解Annotation,那就得自定義Annotation。在講自定義Annotation之前,首先要說的是元Annotation。因為Annotation并不是程序元素,甚至對其進行增刪改也不會影響程序的正常運行。那么如果我們想讓Annotation在程序運行時也起作用,該怎么辦呢?我們要講的元Annotation就是來干這個的,它用來修飾其他的Annotation定義,使Annotation具有不同的作用域。1、使用@Retention我們在創建自定義Annotation時,可以使用@Retention來修飾這個Annotation,用于指定被修飾的Annotation的作用域。@Retention包含一個RetentionPolicy類型的value成員變量,其值可以使如下3個:RetentionPolicy.Class:默認值,編譯器將吧Annotation存儲于class文件中,但運行Java程序時,JVM不會保留Annotation,即只存儲但不參與程序運行;RetentionPolicy.RUNTIME:編譯器將吧Annotation存儲于class文件中,運行Java程序時,JVM也會保留Annotation,即存儲且參與程序運行;RetentionPolicy.SOURCE:編譯器不會存儲Annotation到class文件中,運行Java程序時JVM也不會保留Annotation,即不存儲不保留。很多時候我們需要通過反射獲取注釋信息,所以就需要使用value屬性值為RetentionPolicy.RUNTIME的@Retention,例如下面我們定義了一個名為Param的Annotation,并且可以通過反射來獲取它的注釋信息:@Retention(RetentionPolicy.RUNTIME)public?@interface?Param?{???long?id();???String name();???int?sex()?default?1;}?2、使用@Target@Target也可以用來修飾Annotation定義,它用于指定被修飾的Annotation能用于修飾哪些程序單元,其value值有如下幾個:ElementType.ANNOTATION_TYPE:指定該策略的Annotation只能修飾Annotation;ElementType.CONSTRUCTOR:只能修飾構造器;ElementType.FIELD:只能修飾成員變量;ElementType.LOCAL_VARIABLE:只能修飾局部變量;ElementType.METHOD:只能修飾方法定義;ElementType.PACKAGE:只能修飾包定義;ElementType.PARAMETER:可以修飾參數;ElementType.TYPE:可以修飾類、接口(包括注釋類型)或枚舉定義。下面的例子中,定義Param只能修飾方法:@Target(ElementType.METHOD)public?@interface?Param?{???long?id();???String name();???int?sex()?default?1;}3、使用@Document@Document用于指定被它修飾的Annotation類將被javadoc工具提取成文檔。如果定義Annotation類時使用了@Document修飾,則所有使用該Annotation修飾的程序元素的API文檔中將會包含該Annotation說明。舉個例子來說明:@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.METHOD)@Documentedpublic?@interface?Param?{???long?id();???String name();???int?sex()?default?1;}public?class?Dulven {???public?static?void?main(String[]args) {?}???@Param(id=1001001,name="GISirFive")???public?void?toPerson() {?}}用javadoc提取API,打開API后是這樣的:如果在定義Param時不加@Document,就不會顯示@Param()4、使用@Inherited@Inherited用于指定被其修飾的Annotation定義具有繼承性,被該Annotation修飾的類如果有子類,則子類將會自動被該Annotation修飾。舉個例子:@Inheritedpublic?@interface?Param?{???long?id();???String name();???int?sex()?default?1;}@Param(id=110, name="singer")class?Base{??}?public?class?Dulven?extends?Base{???public?static?void?main(String[]args) {???System.out.println(Dulven.class.isAnnotationPresent(Param.class));???}}上面程序運行會輸出true。???????????????????????????????????????????????三、自定義Annotation除了這4個基本的Annotation,細心的程序員可能會發現還有很多未知的Annotation。其實除了這4個基本的Annotation外,大多數都是我們自定義的,我們可以通過自定義Annotation來使代碼更通俗易懂。1、定義Annotation定義一個新的Annotation與定義一個接口類似,需要使用@interface關鍵字,例如下面定義了一個名為Param的Annotation,并在Test類中使用它:public?@interface?Param?{????}?@Parampublic?class?Test {???public?static?void?main(String[]args) {?????}}在默認情況下,Annotation可用于修飾任何程序元素,包括類、接口、方法等。如普通方法一樣,Annotation還可以帶成員變量,Annotation的成員變量在Annotation定義中以無形參的方法形式來聲明,其方法名和返回值定義了該成員變量的名字和類型,例如:public?@interface?Param?{???long?id();???String name();???int?sex()?default?1;}一旦在Annotation里定義了成員變量,使用時就需要為其指定值,當然我們也可以為成員變量指定默認值,默認值制定方法如同上面的sex,其默認值為1。這樣我們在使用時就不需要為其指定值了,例如:@Param(id=1001, name="旺旺")public?class?Animal {???public?static?void?main(String[]args) {?}}我們可以將Annotation按是否包含成員變量分為兩類:標記Annotation:指沒有定義成員變量的Annotation。這種Annotation僅利用自身的存在與否來為我們提供信息,例如@Override、@Deprecated等。元數據Annotation:指包含成員變量的Annotation,因為它們可以接受更多的元數據。?2、提取Annotation信息當開發者使用Annotation修飾了類、方法、Field等成員之后,正如Annotation的定義所言,Annotaion不能影響程序代碼的執行,無論增加、刪除Annotation,代碼都始終如一的執行。只有通過apt工具對Annotation中的信息進行訪問和處理,我們才能讓程序中的Annotation在程序運行時起一定的作用。所以這些Annotation不會自己生效,必須由開發者提供相應的工具來提取并處理Annotation信息。Java使用Annotation接口來代表程序元素前面的注釋,該接口是所有Annotation類型的付接口。Java5在
查看完整描述

1 回答

?
習慣受傷

TA貢獻885條經驗 獲得超1144個贊

你這個應該發在手記~~~

查看完整回答
1 反對 回復 2017-08-19
  • 1 回答
  • 1 關注
  • 2218 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號