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