摘要:指定該策略的注解只能修飾成員變量。也可以在定義注解的成員變量時(shí)為其指定初始值,指定默認(rèn)值。根據(jù)注解是否可以包含成員變量,可以把注解分為標(biāo)記注解沒(méi)有定義成員變量的注解類(lèi)型被稱(chēng)為標(biāo)記。
@Override
是告訴編譯器檢查這個(gè)方法,保證父類(lèi)要包含一個(gè)被該方法重寫(xiě)的方法,否則編譯出錯(cuò)。
只能修飾方法,不能修飾其他程序元素 。
Java 9 增強(qiáng)的@Deprecated表示某個(gè)程序元素已經(jīng)過(guò)時(shí)。
Java 9 為@Deprecated注解增加了如下兩個(gè)屬性
ForRemoval:該boolean類(lèi)型的屬性指定該API在將來(lái)是否會(huì)被刪除。
Since:該String類(lèi)型的屬性指定該API從哪個(gè)版本被標(biāo)記為過(guò)時(shí)。
public class DeprecatedS { //已過(guò)時(shí),since是從9版本開(kāi)始,forRemoval指定該API將來(lái)會(huì)被刪除 @Deprecated(forRemoval=true,since="9") public void info() { } public static void main(String[] args) { DeprecatedS s = new DeprecatedS(); s.info(); } }抑制編譯器警告:@SuppressWarnings
指示被該注解修飾的程序元素,以及該程序元素中的所有子元素,取消顯示指定的編譯器警告。@SuppressWarnings會(huì)一直作用于該程序元素的所有子元素。
//關(guān)閉整個(gè)類(lèi)里的編譯器警告 @SuppressWarnings(value="unchecked") public class SuppressWarningsS { public static void main(String[] args) { List堆污染警告 與 java 9 增強(qiáng)的@SafeVarargslist = new ArrayList(); } }
當(dāng)把一個(gè)不帶泛型的對(duì)象賦給一個(gè)帶泛型的變量時(shí),往往就會(huì)發(fā)生堆污染
public class SafeVarargsS { public static void main(String[] args) { } //Type safety: Potential heap pollution via varargs parameter list //類(lèi)型安全:通過(guò)varargs參數(shù)列表的潛在堆污染。 public static void ai(List...list) { List[] list2 = list; List myList = new ArrayList<>(); myList.add(new Random().nextInt(100)); list2[0] = myList; String string = list[0].get(0); } }
上面程序中的粗體字代碼已經(jīng)發(fā)生了堆污染,由于該方法有個(gè)形參是List
使用@SafeVarargs
@SafeVarargs public static void ai(ListJava 8的函數(shù)式接口 @FuncationInterface...list) {}
如果接口中只有一個(gè)抽象方法,可以包含多個(gè)默認(rèn)方法或多個(gè)static方法,該接口就是函數(shù)式接口。
@FuncationInterface就是用來(lái)指定某個(gè)接口必須是函數(shù)式接口。
@FunctionalInterface public interface Function{}
FuncationInterface只能修飾接口,不能修飾其他元素
JDK的元注解在java.lang.annotation包下提供了6個(gè)Meta注解(元注解),@Repeatable專(zhuān)門(mén)用于定義java 8新增的重復(fù)注解。
使用@Retention :保留,扣留 Policy:政策,方針
@Retention只能用于修飾注解定義,用于指定被修飾的注解可以保留多長(zhǎng)時(shí)間,他包含一個(gè)RetentionPolicy類(lèi)型的value成員變量,所以使用時(shí)必須為該value成員變量指定值。
Value成員變量的值只能是如下三個(gè)
RetentionPolicy.CLASS : 編譯器將把注解記錄在class中,當(dāng)運(yùn)行java程序時(shí),JVM不可獲得注解信息,這是默認(rèn)值。
RetentionPolicy.REUNTIME:編譯器將把注解記錄在class文件中,當(dāng)運(yùn)行java程序時(shí),JVM也可獲取注解信息,程序可以通過(guò)反射獲得該注解信息。
RetentionPolicy.SOURCE:注解只保留在源代碼中,編譯器直接丟棄這種注解。
使用
@Retention(value = RetentionPolicy.RUNTIME) public @interface My1 {} @Retention(RetentionPolicy.RUNTIME) public @interface My1 {}
使用@Target
只能修飾注解定義,它用于指定被修飾的注解能用于修飾那些程序單元。
@Target元注解也包含一個(gè)value成員變量
成員變量如下
ElementType.ANNOTATION_TYPE:指定該策略的注解只能修飾注解。
ElementType.CONSTRUCTOR:指定該策略的注解只能修飾構(gòu)造器。
ElementType.FIELD:指定該策略的注解只能修飾成員變量。
ElementType.LOCAL_VARIABLE:指定該策略的注解只能修飾局部變量。
ElementType.METHOD:指定該策略的注解只能修飾方法。
ElementType.PACKAGE:指定該策略的注解只能修飾包定義。
ElementType.PARAMETER:指定該策略的注解只能修飾參數(shù)。
ElementType.TYPE:指定該策略的注解只能修飾類(lèi),接口,注解類(lèi)型,枚舉定義。
使用
@Target(value = ElementType.ANNOTATION_TYPE) public @interface My1 {}
使用@Document
@Document用于指定被該元注解修飾的注解類(lèi)將被javadoc工具提取城文檔,如果定義注解類(lèi)時(shí)使用了@Document,則所有使用該注解修飾的程序元素的API文檔中將會(huì)包含該注解說(shuō)明。
使用@Inherited : 可繼承的
指定被他修飾的注解將具有繼承性。
@Inherited public @interface My1 {}
上面程序中代碼表明@My1具有繼承性,如果某個(gè)類(lèi)使用@My1修飾,則該類(lèi)的子類(lèi)將自動(dòng)使用@My1修飾。
檢查其子類(lèi)是否默認(rèn)使用@My1修飾。
@My1 class A{} public class My1_Test extends A { public static void main(String[] args) { System.out.println(My1_Test.class.isAnnotationPresent(My1.class));//true } }自定義注解
定義新的注解使用@Interface關(guān)鍵字定義一個(gè)新的注解類(lèi)型與定義一個(gè)接口非常像,如下
public @interface My1 {}
定義了該注解之后,就可以在程序的任何地方使用該注解。
默認(rèn)情況下,注解可用于修飾任何程序元素,包括類(lèi),接口,方法等。
注解還可以帶成員變量,成員變量在注解定義中以無(wú)形參的方法形式來(lái)聲明,其方法名和返回值定義了該成員變量的名字和類(lèi)型。
public @interface My1 { String name(); int id(); }
一旦在注解里定義了成員變量后,使用該注解時(shí)就應(yīng)該為他的成員變量指定值。
@My1(id=1,name="rrr") class A{} (6) 也可以在定義注解的成員變量時(shí)為其指定初始值,指定默認(rèn)值default。 public @interface My1 { String name() default "ccc"; int id() default 123; }
成員變量指定了值,則默認(rèn)值就不會(huì)起作用。
根據(jù)注解是否可以包含成員變量,可以把注解分為
標(biāo)記注解:沒(méi)有定義成員變量的注解類(lèi)型被稱(chēng)為標(biāo)記。這種注解僅利用自身的存在與否來(lái)提供信息,如@Test、
元數(shù)據(jù)注解:包括成員變量的注解,因?yàn)樗麄兛梢越邮芨嗟脑獢?shù)據(jù),所以也被稱(chēng)為元數(shù)據(jù)注解。
提取注解信息使用注解修飾了類(lèi),方法,成員變量等之后,這些注解不會(huì)自己生效,必須由開(kāi)發(fā)者提供相應(yīng)的工具來(lái)提取并處理注解信息。
AnnotatedElement接口,該接口代表程序中可以接受注解的程序元素,該接口主要有如下個(gè)實(shí)現(xiàn)類(lèi):
Class:類(lèi)定義
Constructor:構(gòu)造器定義
Field:類(lèi)的成員變量定義
Method:類(lèi)的方法定義
Package:類(lèi)的包定義
只有當(dāng)定義注解時(shí)使用了@Retention(RetentionPolicy.RUNTIME)修飾,該注解才會(huì)在運(yùn)行時(shí)可見(jiàn),JVM才會(huì)在裝載class文件時(shí)讀取保存在class文件中的注解信息。
獲取My2類(lèi)的方法上的Annotation
public class My2 { @My1(id =123,name ="dsds") public void info() { } } public class GetMy2Annotation{ public static void main(String[] args) throws Exception{ Class> forName = Class.forName("annotations.My2");//加載類(lèi) Method method = forName.getMethod("info");//得到方法 Annotation[] annotations = method.getAnnotations();//得到方法上所有注解 //@annotations.My1(name="dsds", id=123) for (Annotation annotation : annotations) { System.out.println(annotation); } } }
訪(fǎng)問(wèn)注解中的元數(shù)據(jù)
public class GetMy2Annotation{ public static void main(String[] args) throws Exception{ Class> forName = Class.forName("annotations.My2");//加載類(lèi) Method method = forName.getMethod("info");//得到方法 Annotation[] annotations = method.getAnnotations();//得到方法上所有注解 /* * 123 * dsds * */ for (Annotation annotation : annotations) { if (annotation instanceof My1) { System.out.println(((My1)annotation).id()); System.out.println(((My1)annotation).name()); } } } }
利用注解模擬@Test的JUnit效果
public class RunTest { public static void main(String[] args) throws Exception { Class> forName = Class.forName("annotations.RunTest_JUnit");//加載類(lèi) Method[] methods = forName.getDeclaredMethods();//獲得本類(lèi)所有方法 int success = 0;//成功方法 int fail = 0;//失敗方法 for (Method method : methods) { System.out.println(method); System.out.println(method.isAnnotationPresent(Testable.class)); if (method.isAnnotationPresent(Testable.class)) { try { //抑制private訪(fǎng)問(wèn)修飾符 method.setAccessible(true); method.invoke( null); success++; } catch (Exception e) { fail++; } } } System.out.println("成功方法有:" + success +"個(gè) 失敗的有:"+fail+"個(gè)"); } } class RunTest_JUnit{ @Testable private static void t() { System.out.println("=========================t"); } private static void t1() { } @Testable private static void t2() { System.out.println("=========================t2"); } @Testable private static void r2() { System.out.println("=========================r2"); throw new RuntimeException("出錯(cuò)誤啦"); } } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Testable{ } Output: private static void annotations.RunTest_JUnit.t1() false private static void annotations.RunTest_JUnit.t() true =========================t private static void annotations.RunTest_JUnit.r2() true =========================r2 private static void annotations.RunTest_JUnit.t2() true =========================t2 成功方法有:2個(gè) 失敗的有:1個(gè)
上面的@Testable用于標(biāo)記那些方法是可測(cè)試的,該注解可以作為JUnit測(cè)試框架的補(bǔ)充,在JUnit框架中他要求測(cè)試用例的測(cè)試方法必須以test開(kāi)頭。
Java 8 新增的重復(fù)注解@Retention(RetentionPolicy.RUNTIME) @Target(value=ElementType.TYPE) @Repeatable(value=FkTags.class)//只能可以包容它的容器類(lèi) public @interface FkTag { String name() default "王自強(qiáng)"; int id(); } @Retention(RetentionPolicy.RUNTIME) @Target(value=ElementType.TYPE) public @interface FkTags { FkTag[] value(); } //@FkTags({@FkTag(id=1,name="dsd"),@FkTag(id=213)}) @FkTag(id=123) @FkTag(id=1233) public class Test_FkTage { public static void main(String[] args) { Classcl = Test_FkTage.class;//獲取類(lèi) //這個(gè)方法可以獲得多個(gè)重復(fù)注解,而getDeclaredAnnotation只能獲取一個(gè) FkTag[] annotationsByType = cl.getAnnotationsByType(FkTag.class); for (FkTag fkTag : annotationsByType) { System.out.println(fkTag.id()+" "+ fkTag.name()); } FkTags annotation = cl.getAnnotation(FkTags.class); System.out.println(annotation); } } Output 123 王自強(qiáng) 1233 王自強(qiáng) @fkAnnotation.FkTags(value={@fkAnnotation.FkTag(name="王自強(qiáng)", id=123), @fkAnnotation.FkTag(name="王自強(qiáng)", id=1233)})
如上的重復(fù)注解只是一種簡(jiǎn)便的寫(xiě)法,運(yùn)用@Repeatable注解來(lái)制定他的容器注解類(lèi)即可。
容器注解類(lèi)注解的保留期必須比他所包含的注解的保留期更長(zhǎng),否則編譯器報(bào)錯(cuò)。
Java 8新增的類(lèi)型注解編寫(xiě)自定義注解時(shí)未寫(xiě)@Inherited的運(yùn)行結(jié)果 | 編寫(xiě)自定義注解時(shí)寫(xiě)了@Inherited的運(yùn)行結(jié)果 | |
---|---|---|
子類(lèi)的類(lèi)上能否繼承到父類(lèi)的類(lèi)上的注解? | 否 | 能 |
子類(lèi)方法,實(shí)現(xiàn)了父類(lèi)上的抽象方法,這個(gè)方法能否繼承到注解? | 否 | 否 |
子類(lèi)方法,實(shí)現(xiàn)了父類(lèi)上的方法,這個(gè)方法能否繼承到注解? | 能 | 能 |
子類(lèi)方法,覆蓋了父類(lèi)上的方法,這個(gè)方法能否繼承到注解? | 否 | 否 |
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/69333.html
注解 注解(一種元數(shù)據(jù)形式)提供有關(guān)不屬于程序本身的程序的數(shù)據(jù),注解對(duì)它們注解的代碼的操作沒(méi)有直接影響。 注解有許多用途,其中包括: 編譯器的信息 — 編譯器可以使用注解來(lái)檢測(cè)錯(cuò)誤或抑制警告。 編譯時(shí)和部署時(shí)處理 — 軟件工具可以處理注解信息以生成代碼、XML文件等。 運(yùn)行時(shí)處理 — 可以在運(yùn)行時(shí)檢查某些注解。 本課程介紹了可以使用注解的位置,以及如何應(yīng)用注解,Java平臺(tái)標(biāo)準(zhǔn)版(Java S...
摘要:注解是的一個(gè)新特性。很重要,生產(chǎn)中我們開(kāi)發(fā)常用此值表示注解是否可被子元素繼承。類(lèi)注解方法注解通過(guò)反射獲取方法對(duì)象此部分內(nèi)容可參考通過(guò)反射獲取注解信息注解處理器實(shí)戰(zhàn)接下來(lái)我通過(guò)在公司中的一個(gè)實(shí)戰(zhàn)改編來(lái)演示一下注解處理器的真實(shí)使用場(chǎng)景。 前言:Java 注解,對(duì)于很多人都不陌生了,但是在公司的實(shí)際開(kāi)發(fā)中,可能讓我們自己去定義注解并應(yīng)用到生產(chǎn)環(huán)境中的機(jī)會(huì)比較少,所以會(huì)導(dǎo)致一部分人對(duì)注解的理解...
摘要:注解有以下幾個(gè)知識(shí)點(diǎn)元數(shù)據(jù)注解的分類(lèi)內(nèi)置注解自定義注解注解處理器本文先介紹前面?zhèn)€知識(shí)點(diǎn)元數(shù)據(jù)注解的分類(lèi)內(nèi)置注解自定義注解。注解相當(dāng)于是一種嵌入在程序中的元數(shù)據(jù),可以使用注解解析工具或編譯器對(duì)其進(jìn)行解析,也可以指定注解在編譯期或運(yùn)行期有效。 大家好,我是樂(lè)字節(jié)的小樂(lè),上次說(shuō)過(guò)了Java多態(tài)的6大特性|樂(lè)字節(jié),接下來(lái)我們來(lái)看看Java編程里的注解。showImg(https://segme...
摘要:中提供了前四個(gè)元注解。在中新添加了最后一個(gè)注解。指定了注解可以用于的范圍。可以默認(rèn)設(shè)置為空字符串如果沒(méi)有默認(rèn)值的話(huà),在使用的時(shí)候則需要對(duì)它進(jìn)行賦值。反射程序運(yùn)行時(shí)獲取注解的值,設(shè)置為??梢允褂每兆址? 分類(lèi) 元注解(meta-annotation) java元注解就是用來(lái)注解其他注解??梢岳斫鉃樵⒔馐瞧渌x的注解的基礎(chǔ)。元注解有 @Retention、@Documented、@Ta...
摘要:注解添加了注解的注解,所注解的類(lèi)的子類(lèi)也將擁有這個(gè)注解注解父類(lèi)子類(lèi)會(huì)把加在上的繼承下來(lái)在接口上添加注解,然后類(lèi)實(shí)現(xiàn)了接口,類(lèi)不會(huì)擁有接口上的注解。如果父類(lèi)刪除了該方法,則子類(lèi)會(huì)報(bào)錯(cuò)。注解表示被注解的元素已被棄用。 Java的注解在實(shí)際項(xiàng)目中使用得非常的多,特別是在使用了Spring之后。本文會(huì)介紹Java注解的語(yǔ)法,以及在Spring中使用注解的例子。 注解的語(yǔ)法 注解的例子 以Ju...
閱讀 859·2019-08-30 15:54
閱讀 3325·2019-08-29 15:33
閱讀 2709·2019-08-29 13:48
閱讀 1235·2019-08-26 18:26
閱讀 3342·2019-08-26 13:55
閱讀 1499·2019-08-26 10:45
閱讀 1176·2019-08-26 10:19
閱讀 317·2019-08-26 10:16