我們在平時的開發過程中看到很多如@Override,@SuppressWarnings,@Test等樣式的代碼就是注解,注解是放到類、構造器、方法、屬性、參數前的標記。
給某個類、方法..添加了一個注解,這個環節僅僅是做了一個標記,對代碼本身并不會造成任何影響,需要后續環節的配合,需要其他方法對該注解賦予業務邏輯處理。就如同我們在微信上發了一個共享定位,此時并沒有什么用,只有當后面其他人都進入了這個共享定位,大家之間的距離才能明確,才知道該怎么聚在一起。
注解分為三類:
如@Override,@SuppressWarnings都是編譯器使用到的注解,作用是告訴編譯器一些事情,而不會進入編譯后的.class文件。
@Override:告訴編譯器檢查一下是否重寫了父類的方法;
@SuppressWarnings:告訴編譯器忽略該段代碼產生的警告;
對于開發人員來說,都是直接使用,無需進行其他操作
需要通過工具對.class字節碼文件進行修改的一些注解,某些工具會在類加載的時候,動態修改用某注解標注的.class文件,從而實現一些特殊的功能,一次性處理完成后,并不會存在于內存中,都是非常底層的工具庫、框架會使用,對于開發人員來說,一般不會涉及到。
一直存在于JVM中,在運行期間可以讀取的注解,也是最常用的注解,如Spring的@Controller,@Service,@Repository,@AutoWired,Mybatis的@Mapper,Junit的@Test等,這類注解很多都是工具框架自定義在運行期間發揮特殊作用的注解,一般開發人員也可以自定義這類注解。
我們使用@interface來定義一個注解
/***定義一個Table注解*/public@interfaceTable{Stringvalue()default"";}/***定義一個Colum注解*/public@interfaceColum{Stringvalue()default"";Stringname()default"";StringdictType()default"";}
這樣就簡單地將一個注解定義好了
我們上面定義的注解主要用到了String類型,但實際上還可以是基本數據類型(不能為包裝類)、枚舉類型。
注解也有一個約定俗成的東西,最常用的參數應該命名為value,同時一般情況下我們都會通過default參數設置一個默認值。
但這樣是不是就滿足于我們的使用了呢,我想把@Table
注解僅用于類上,@Colum
注解僅用于屬性上,怎么辦?而且開始提到的三類注解,一般開發人員用的都是運行期的注解,那我們定義的是嗎?
要回答這些問題,就需要引入一個概念“元注解”。
可以修飾注解的注解即為元注解,Java已經定義了一些元注解,我們可以直接使用。
顧名思義指定注解使用的目標對象,參數為ElementType[]
public@interfaceTarget{/***Returnsanarrayofthekindsofelementsanannotationtype*canbeappliedto.*@returnanarrayofthekindsofelementsanannotationtype*canbeappliedto*/ElementType[]value();}
而下面是ElementType枚舉中定義的屬性,不設置Target的時候,除了TYPE_PARAMETER,TYPE_USE,其他地方都相當于配置上了。
publicenumElementType{/**通過ElementType.TYPE可以修飾類、接口、枚舉*/TYPE,/**通過ElementType.FIELD可以修飾類屬性*/FIELD,/**通過ElementType.METHOD可以修飾方法*/METHOD,/**通過ElementType.PARAMETER可以修飾參數(如構造器或者方法中的)*/PARAMETER,/**通過ElementType.CONSTRUCTOR可以修改構造器*/CONSTRUCTOR,/**通過ElementType.LOCAL_VARIABLE可以修飾方法內部的局部變量*/LOCAL_VARIABLE,/**通過ElementType.ANNOTATION_TYPE可以修飾注解*/ANNOTATION_TYPE,/**通過ElementType.PACKAGE可以修飾包*/PACKAGE,/***可以用在Type的聲明式前**@since1.8*/TYPE_PARAMETER,/***可以用在所有使用Type的地方(如泛型、類型轉換等)**@since1.8*/TYPE_USE}
我們主要說一下ElementType.PACKAGE和1.8添加的ElementType.TYPE_PARAMETER和ElementType.TYPE_USE
ElementType.PACKAGE
@Target(ElementType.PACKAGE)public@interfaceTable{Stringvalue()default"";}
含義是用來修飾包,但我們用來修飾包的時候卻提示錯誤
我們按照提示創建package-info.java文件,這里需要注意一下,通過IDE 進行new --> Java Class是創建不了的,需要通過new File文件創建
@Tablepackageannotation;classPackageInfo{publicvoidhello(){System.out.println("hello");}}
ElementType.TYPE_PARAMETER和ElementType.TYPE_USE
這兩個一起說,因為它們有相似之處。都是Java1.8后添加的
@Target(ElementType.TYPE_USE)public@interfaceNoneEmpty{Stringvalue()default"";}@Target(ElementType.TYPE_PARAMETER)public@interfaceNoneBlank{Stringvalue()default"";}
很明顯使用ElementType.TYPE_PARMETER修飾的注解@NoneBlank無法在泛型使用的時候編譯通過,僅能用于類的泛型聲明,而通過ElementType.TYPE_USE修飾的注解@NoneEmpty可以。
可以用于定義注解的生命周期,參數為枚舉RetentionPolicy,包括了SOURCE,CLASS,RUNTIME
@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.ANNOTATION_TYPE)public@interfaceRetention{/***Returnstheretentionpolicy.*@returntheretentionpolicy*/RetentionPolicyvalue();}publicenumRetentionPolicy{/***僅存在于源代碼中,編譯階段會被丟棄,不會包含于class字節碼文件中.*/SOURCE,/***【默認策略】,在class字節碼文件中存在,在類加載的時被丟棄,運行時無法獲取到*/CLASS,/***始終不會丟棄,可以使用反射獲得該注解的信息。自定義的注解最常用的使用方式。*/RUNTIME}
表示是否將此注解的相關信息添加到javadoc文檔中
定義該注解和子類的關系,使用此注解聲明出來的自定義注解,在使用在類上面時,子類會自動繼承此注解,否則,子類不會繼承此注解。注意,使用@Inherited聲明出來的注解,只有在類上使用時才會有效,對方法,屬性等其他無效。
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)@Inheritedpublic@interfacePerson{Stringvalue()default"man";}@PersonpublicclassParent{}//子類也擁有@Person注解classSonextendsParent{}
用@interface定義注解
可以添加多個參數,核心參數按約定用value,為每個參數可以設置默認值,參數類型包括基本類型、String和枚舉
可以使用元注解來修飾注解,元注解包括多個,必須設置@Target
和@Retention
,@Retention
一般設置為RUNTIME
。
我們前面已經提到光配置了注解,其實沒有作用,需要通過相應的代碼來實現該注解想要表達的邏輯。
注解定義后也是一種class,所有的注解都繼承自java.lang.annotation.Annotation
,因此,讀取注解,需要使用反射API。
//定義的注解@Target(ElementType.FIELD)@Retention(RetentionPolicy.RUNTIME)public@interfaceColum{Stringvalue()default"";//用于表示某個屬性代表的中文含義Stringname()default"";}
用注解@Colum來修飾某個類的屬性
publicclassPerson{@Colum(name="姓名")privateStringname;@Colum(name="性別")privateStringgender;@Colum(name="年齡")privateintage;@Colum(name="住址")privateStringaddress;publicStringgetName(){returnname;}publicvoidsetName(Stringname){this.name=name;}publicStringgetGender(){returngender;}publicvoidsetGender(Stringgender){this.gender=gender;}publicintgetAge(){returnage;}publicvoidsetAge(intage){this.age=age;}publicStringgetAddress(){returnaddress;}publicvoidsetAddress(Stringaddress){this.address=address;}}
通過反射讀取這個類的所有字段的中文含義,并保存到list中,然后打印出來
publicstaticvoidmain(String[]args)throwsClassNotFoundException{List<String>columNames=newArrayList<>();Classclazz=Class.forName("annotation.Person");//獲取Person類所有屬性Field[]fields=clazz.getDeclaredFields();for(Fieldfield:fields){//獲取該屬性的Colum注解Columcolum=field.getAnnotation(Colum.class);//或者可以先判斷有無該注解field.isAnnotationPresent(Colum.class);//將該屬性通過注解配置好的中文含義取出來放到集合中columNames.add(colum.name());}//打印集合columNames.forEach((columName)->System.out.println(columName));}
結果如下:
姓名性別年齡住址
比如我們有一些常見的應用場景,需要把網站上的列表導出成excel表格,我們通過注解的方式把列名配置好,再通過反射讀取實體需要導出(是否需要導出,也可通過注解配置)的每個字段的值,從而實現excel導出的組件。
本文只是拋磚引玉地講解了注解的基本概念,注解的作用,幾種元注解的功用以及使用方法,并通過一個簡單的例子講解了一下注解的處理,并不全面,文中通過Field講解了注解的基本Api,但注解還可以修飾類、構造器、方法等,也有相對應的注解處理方法,大家可自行查一下API手冊相關內容,大同小異,有不對之處,請批評指正,望共同進步,謝謝! <br>
<hr> <font color="Darkorange" size="4px"><b>關注微信公眾號【<a href="http://mp.weixin.qq.com/s?__biz=MzU0OTg3ODQxNA==&mid=100000173&idx=1&sn=1af862786cc9126634f630a5d4d37d17&chksm=7ba86e4c4cdfe75aa0ce43095cbc2babff63affb0a5e18b5e8ff6a8f6fdc4b4bc129d6e7af10#rd">程序員的夢想</a>】,專注于Java,SpringBoot,SpringCloud,微服務,Docker以及前后端分離等全棧技術。</b></font>
關于Java中Annotation注解的作用是什么就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
本文由 貴州做網站公司 整理發布,部分圖文來源于互聯網,如有侵權,請聯系我們刪除,謝謝!
c語言中正確的字符常量是用一對單引號將一個字符括起表示合法的字符常量。例如‘a’。數值包括整型、浮點型。整型可用十進制,八進制,十六進制。八進制前面要加0,后面...
2022年天津專場考試原定于3月19日舉行,受疫情影響確定延期,但目前延期后的考試時間推遲。 符合報名條件的考生,須在規定時間登錄招考資訊網(www.zha...
:喜歡聽,樂意看。指很受歡迎?!巴卣官Y料”喜聞樂見:[ xǐ wén lè jiàn ]詳細解釋1. 【解釋】:喜歡聽,樂意看。指很受歡迎。2. 【示例】:這是...
【資料圖】對 于 國旗的拼音怎么拼寫聲調_國旗的拼音的知識大家了解嗎?以下就是小編整理的關于國旗的拼音怎么拼寫聲調_國旗的拼音的介紹,希望對大家有幫助!1、首先給“國”字的聲母“G”打蠟。2、然后寫最后的“U”,再寫“O”。3、最后用gu]調標注“uo”。畫4、然后“flag”這個詞先用首字母“Q”拼寫。桃疇5、再寫“l”。6、最后,標出音調[q]。7、國板旗。所以拼音是這樣寫的。本文到此結束,希...
毛利率和凈利率的區別是什么?1、毛利率和凈利率的定義不同:毛利率是毛利與銷售收入(或營業收入)的百分比,其中毛利是收入和與收入相對應的營業成本之間的差額。凈利率是指凈銷售額占營業收入的百分比或投入資本的百分比。這個百分比可以綜合反映一個企業或者一個行業的經營效率。凈利率是說明企業收入1塊錢能凈賺多少錢。2、毛利率和凈利率的計算公式不同:毛利率=毛利/營業收入×100%=(主營業務收入-...
大量股票解禁反而暴漲咋回事?股票跌漲不由解禁決定,且股票公開不代表控股股東立刻減持,股票跌漲由供求關系求、資金額、銷售績業、政策、消息等各個方面因素決定。股票解禁代表著大量的非流通股可以進行流通,減持需要提早傳出公示,非流通股占總股本5%以上的,一般需 要2年以上才可以減持,非流通股占總股本小于5%的,一般規定在一年之后才可以減持。解禁股票當天一般漲還是跌?跌,股票解禁后第一天一般是下跌,下跌的概...