使用@interface自定義註解時,自動繼承了java.lang.annotation.Annotation接口,由編譯程序自動完成其餘細節。在定義註解時,不能繼承其餘的註解或接口。@interface用來聲明一個註解,其中的每個方法其實是聲明瞭一個配置參數。方法的名稱就是參數的名稱,返回值類型就是參數的類型(返回值類型只能是基本類型、Class、String、enum)。能夠經過default來聲明參數的默認值。html
定義註解格式:
public @interface 註解名 {定義體}java
註解參數的可支持數據類型:git
1.全部基本數據類型(int,float,boolean,byte,double,char,long,short)
2.String類型
3.Class類型
4.enum類型
5.Annotation類型
6.以上全部類型的數組github
Annotation類型裏面的參數該怎麼設定:
第一,只能用public或默認(default)這兩個訪問權修飾.例如,String value();這裏把方法設爲defaul默認類型;
第二,參數成員只能用基本類型byte,short,char,int,long,float,double,boolean八種基本數據類型和 String,Enum,Class,annotations等數據類型,以及這一些類型的數組.例如,String value();這裏的參數成員就爲String;
第三,若是隻有一個參數成員,最好把參數名稱設爲"value",後加小括號.例:下面的例子FruitName註解就只有一個參數成員。數組
簡單的自定義註解和使用註解實例:
app
package annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 水果名稱註解 * @author peida * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitName { String value() default ""; }
package annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * 水果顏色註解 * @author peida * */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface FruitColor { /** * 顏色枚舉 * @author peida * */ public enum Color{ BULE,RED,GREEN}; /** * 顏色屬性 * @return */ Color fruitColor() default Color.GREEN; }
package annotation; import annotation.FruitColor.Color; public class Apple { @FruitName("Apple") private String appleName; @FruitColor(fruitColor=Color.RED) private String appleColor; public void setAppleColor(String appleColor) { this.appleColor = appleColor; } public String getAppleColor() { return appleColor; } public void setAppleName(String appleName) { this.appleName = appleName; } public String getAppleName() { return appleName; } public void displayName(){ System.out.println("水果的名字是:蘋果"); } }
元註解的做用就是負責註解其餘註解。Java5.0定義了4個標準的meta-annotation類型,它們被用來提供對其它 annotation類型做說明。Java5.0定義的元註解:
1.@Target,用於描述註解的使用範圍(方法、構造方法、成員變量、枚舉值)
ide
取值(ElementType)有:函數
1.CONSTRUCTOR:用於描述構造器
2.FIELD:用於描述域
3.LOCAL_VARIABLE:用於描述局部變量
4.METHOD:用於描述方法
5.PACKAGE:用於描述包
6.PARAMETER:用於描述參數
7.TYPE:用於描述類、接口(包括註解類型) 或enum聲明工具
2.@Retention,表示須要在什麼級別保存該註釋信息,用於描述註解的生命週期源碼分析
取值(RetentionPoicy)有:
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在運行時有效(即運行時保留)(屬性值是RUTIME,這樣註解處理器能夠經過反射,獲取到該註解的屬性值)
3.@Documented 用於描述其它類型的annotation應該被做爲被標註的程序成員的公共API,所以能夠被例如javadoc此類的工具文檔化
4.@Inherited@Inherited 元註解是一個標記註解,@Inherited闡述了某個被標註的類型是被繼承的。若是一個使用了@Inherited修飾的annotation類型被用於一個class,則這個annotation將被用於該class的子類。
第一步:新建一個annotation,名字爲:MyAnnotation.java。
package com.dragon.test.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Created by gmq on 2015/9/10. */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String hello () default "hello"; String world(); }
第二步:創建一個MyTest.java 來使用上面的annotation。
package com.dragon.test.annotation; /** * Created by gmq on 2015/9/10. */ public class MyTest { @MyAnnotation(hello = "Hello,Beijing",world = "Hello,world") public void output() { System.out.println("method output is running "); } }
第三步:用反射機制來調用註解中的內容
package com.dragon.test.annotation; import java.lang.annotation.Annotation; import java.lang.reflect.Method; /** * 用反射機制來調用註解中的內容 * Created by gmq on 2015/9/10. */ public class MyReflection { public static void main(String[] args) throws Exception { // 得到要調用的類 Class<MyTest> myTestClass = MyTest.class; // 得到要調用的方法,output是要調用的方法名字,new Class[]{}爲所須要的參數。空則不是這種 Method method = myTestClass.getMethod("output", new Class[]{}); // 是否有類型爲MyAnnotation的註解 if (method.isAnnotationPresent(MyAnnotation.class)) { // 得到註解 MyAnnotation annotation = method.getAnnotation(MyAnnotation.class); // 調用註解的內容 System.out.println(annotation.hello()); System.out.println(annotation.world()); } System.out.println("----------------------------------"); // 得到全部註解。必須是runtime類型的 Annotation[] annotations = method.getAnnotations(); for (Annotation annotation : annotations) { // 遍歷全部註解的名字 System.out.println(annotation.annotationType().getName()); } } }
輸出:
Hello,Beijing
Hello,world
參考:https://www.cnblogs.com/gmq-sh/p/4798194.html
註解(Annotation),也叫元數據(Metadata),是Java5的新特性,JDK5引入了Metadata很容易的就可以調用Annotations。註解與類、接口、枚舉在同一個層次,並能夠應用於包、類型、構造方法、方法、成員變量、參數、本地變量的聲明中,用來對這些元素進行說明註釋。
(1)以@interface關鍵字定義
(2)註解包含成員,成員以無參數的方法的形式被聲明。其方法名和返回值定義了該成員的名字和類型。
(3)成員賦值是經過@Annotation(name=value)的形式。
(4)註解須要標明註解的生命週期,註解的修飾目標等信息,這些信息是經過元註解實現。
以 java.lang.annotation 中定義的 Target 註解來講明:
@Retention(value = RetentionPolicy.RUNTIME) @Target(value = { ElementType.ANNOTATION_TYPE } ) public @interface Target { ElementType[] value(); }
源碼分析以下:
第一:元註解@Retention,成員value的值爲RetentionPolicy.RUNTIME。
第二:元註解@Target,成員value是個數組,用{}形式賦值,值爲ElementType.ANNOTATION_TYPE
第三:成員名稱爲value,類型爲ElementType[]
另外,須要注意一下,若是成員名稱是value,在賦值過程當中能夠簡寫。若是成員類型爲數組,可是隻賦值一個元素,則也能夠簡寫。如上面的簡寫形式爲:
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.ANNOTATION_TYPE) public @interface Target { ElementType[] value(); }
註解的分類有兩種分法:
第一種分法
一、基本內置註解,是指Java自帶的幾個Annotation,如@Override、Deprecated、@SuppressWarnings等;
二、元註解(meta-annotation),是指負責註解其餘註解的註解,JDK 1.5及之後版本定義了4個標準的元註解類型,以下:
@Target
@Retention
@Documented
@Inherited
三、自定義註解,根據須要能夠自定義註解,自定義註解須要用到上面的meta-annotation
參考:https://blog.csdn.net/github_35180164/article/details/52107204
@Retention是java當中的一個元註解,該元註解一般都是用於對軟件的測試
@Retention(RetentionPolicy.RUNTIME) @interface Task{.......}
參數RetentionPolicy.RUNTIME就說明了,@Task註解在程序運行時是可見的
RetentionPolicy的枚舉類型還有SOURCE、CLASS分別指定註解對於那個級別是可見的,可是,咱們通常都是用RUNTIME,由於這是在程序運行時能夠對註解進行讀取,從而易於軟件的測試
在java虛擬機JVM在運行時,就會將類進行加載,這時,每一個類都會生成一個Class數據類型的對象(Class類在java.lang.Class中),這個對象就是對應類的「運行時對象」,經過這個運行時對象,就可以獲取對應類的許多信息,也就是說,運行時對象實際就是對應類的一個映射,這就java的內省反射機制
① 獲取對應類的Class數據類型的運行時對象的引用——getClass()
public class Point{.....} //聲明一個類 Point pt = new Point(); //建立對應類的實例對象 Class cls = pt.getClass() ; //則cls 就指向了Point類的運行時對象
②運行時對象cls的成員函數
<1>public String getName() 返回對應類的類名 <2>public boolean isAnnotationPresent(註解名.class) 斷定指定的"註解"是否在運行時註解了 cls 的對應類 <3>public boolean isAnnotation(); 斷定cls 是否在運行時被任何註解 註解過 <4>public A getAnnotation(註解名.class) A 指的是一個註解的類型,具體用法以下: @Retention(RetentionPolicy.RUNTIME) //指定@Task運行時可見 @interface Task{String descirption(); } @Task(descroption="NoFinished") //爲computer做注 class Computer{.....} 則 Computer my = new Computer() ; Class cls = my.getClass() ; Task tk = (Task) cls.getAnnotation(Task.class); //這時 tk 就指向了標註Computer的註解@Task tk.description(); //調用@Task中的description(),輸出"NoFinishing" <5> public Method[] getMethods() 返回由對應類中的全部的方法造成的Method數組,每一個Method對象都惟一對應 一個對應類中的方法,經過Method[i]就能夠得到對應方法的信息 (Method類在java.lang.reflect.Method中) 這個Method類也有不少成員方法,用來獲取對應的方法的信息 如也有: public boolean isAnnotationPresent(註解名.class) 斷定對應的方法是否被指定的注所註解 public A getAnnotation(註解名.class) 用法和上面的講述的同樣,之不過建立的註解型的引用變量指向的是 "標記對應方法的註解"
參考:https://www.cnblogs.com/PengLee/p/3902836.html