目錄
一、自定義Annotation
先來看兩個自定義註解java文件:
1.JZDesc.java
package sn.test.test6.annotation;
import java.lang.annotation.*;
/**
* 自定義Annotation:JZDesc
*/
@Documented
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface JZDesc {
public String value();
}
2.JZMethod.java
package sn.test.test6.annotation;
import java.lang.annotation.*;
/**
* 自定義Annotation:JZMethod
*/
@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface JZMethod {
String name();
String sex();
int age();
}
看到這裏,你可能徹底蒙圈了,一上來就這麼晦澀, 可能你有很多疑問,比如:
- @interface是什麼意思?和interface關鍵字有什麼關係嗎?
- Documented、Target、Retention 是神馬東東?
- ElementType、RetentionPolicy又是啥玩意兒?
不要着急,我下面會一一解答。
首先,@interface 也是一個關鍵字,和interface關鍵字沒有任何關係,僅僅說明要設計Annotation必須要指定類型爲@interface
其次,爲了更清楚的解釋上面(2)(3)東東的作用,不得不先來看看java的幾個原生註解
二、Java元註解
1.什麼是元註解?
-定義:作用於註解上的註解,白話就是:這些註解操作的對象還是註解。
2.常見的元註解有哪些?
-分類:@Document ,@Target ,@Retention ,@Inherited
3.元註解用來幹嘛的?
作用:
1. @Document :目的讓這個Annotation類型的信息可以顯示在javaAPI說明文檔中,如果不添加的話,使用javadoc生成 的接口文檔中將沒有這個類型生成的任何信息。
2. @Target:作用是指定這個Annotation可以用在哪些元素之上,如果不指定,則是ElementType枚舉值的最大範圍
3. @Retention:作用是指定這個Annotation的類型信息保留的範圍,如果不指定,則是RetentionPolicy枚舉值的最大範圍
解答了 Documented、Target、Retention 是神馬? 這個疑問,那麼再來看看第二個疑問:
ElementType、RetentionPolicy又是啥玩意? 要解釋這兩個問題,那就不得不提一個jar包:java.lang.annotation,具體往下看
三、java.lang.annotation包
java.lang.annotation包中有兩個源文件:ElementType.java,RetentionPolicy.java,下面來看下這兩個源文件的內容
1.ElementType.java 源文件
public enum ElementType {
TYPE,
FIELD,
METHOD,
PARAMETER,
CONSTRUCTOR,
LOCAL_VARIABLE,
ANNOTATION_TYPE,
PACKAGE
}
ElementType,一個enum類型,用來定義Annotation可以作用哪些元素上,有如下幾種:
* 1:TYPE(類型), 是指可以用在Class,Interface,Enum和Annotation類型上
* 2:FIELD(屬性),
* 3:METHOD(方法),
* 4:PARAMETER(參數),
* 5:CONSTRUCTOR(構造函數),
* 6:LOCAL_VARIABLE(局部變量),
* 7:ANNOTATION_TYPE,(註解)
* 8:PACKAGE(包)
2.RetentionPolicy 源文件
public enum RetentionPolicy {
SOURCE,
CLASS,
RUNTIME
}
1. SOURCE-代表的是這個Annotation類型的信息只會保留在程序源碼裏,一旦編譯過後,Annotation的信息就會消失,不會出現在.class文件中
2. CLASS-表示這個Annotation類型的信息既保留在程序源碼裏,又保留在編譯後的.class文件中,但是執行時,不會被加載到JVM中
3. RUNTIME-表示這個Annotation類型的信息會分別保留在在源碼裏、編譯好的.class文件中,執行時也會被加載到JVM中
經過上面的講解,你可能大概瞭解上文中自定義Annotation文件 JZMethod.java 和JZDesc.java文件的大致內容,那麼又有一個疑問,自己一註解{}內部定義的比如 value() 是什麼?有什麼要注意的地方嗎嗎?
public @interface JZDesc {
public String value();//參數成員1
}
public @interface JZMethod {
String name();//參數成員1
String sex();//參數成員2
int age();//參數成員3
}
首先,Annotation內部定義的是註解的參數成員,如@Resource(name="aaa",description="方法1"),那麼name和description都是@Resource註解的參數成員,參數成員要指定參數的數據類型,如String,int,byte etc,並且可以用public修飾,也可以省略
其次,一般參數成員定義注意項有幾點:
1. 只能用public或默認(default)這兩個訪問權修飾.例如,String value();這裏把方法設爲defaul默認類型.
2. 參數成員只能用基本類型byte,short,char,int,long,float,double,boolean八種基本數據類型,String,Enum,Class,annotations等數據類型,以及這一些類型的數組.例如,String value();value()參數成員就爲String類型* * 3.如果只有一個參數成員,最好把參數名稱設爲"value",後加小括號比如:String value();
ok,上面基本上全部解釋了自定義java文件中包含的內容代表的含義,那麼既然定義了兩個註解文件:JZDesc.java、JZMethod.java,那麼該如何應用呢?下面將簡單介紹如何將註解作用到其他類上
四、自定義Annotation的使用
1.AnnotationUsage.java Annotation(JZDesc、JZMethod)使用示例
,
package sn.test.test6.annotation;
@JZDesc("這是本教主自定義的一個註解,作用元素Class")
public class AnnotationUsage {
@JZMethod(name = "唐僧",sex = "男",age = 20)
public String man(){
return "這是一個人";
}
@JZMethod(name = "悟空",sex = "男",age = 500)
public String monkey(){
return "這是一隻成精的猴子";
}
@JZMethod(name = "沙僧",sex = "男",age = 1000)
public String monster(){
return "這是一個妖怪";
}
}
2.Client.java 客戶端Annotation實際測試
package sn.test.test6.annotation;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
public class Client {
public static void main(String [] args) throws ClassNotFoundException {
System.out.println("===開始測試了====");
Class testClass=Class.forName("sn.test.test6.annotation.AnnotationUsage");
Method[] methods=testClass.getMethods();
/**
* 1.獲取作用在Class上的JZDesc類型註解
*/
//判斷JZDesc註解是否存在
boolean flag=testClass.isAnnotationPresent(JZDesc.class);
//存在
if (flag){
//獲取註解-getAnnotation()
JZDesc jzDesc=(JZDesc)testClass.getAnnotation(JZDesc.class);
//獲取參數成員
System.out.println("JZDesc參數成員內容獲取爲:"+jzDesc.value());
}
/**
* 2.獲取作用在Method上的JZMethod類型註解
*/
//判斷哪些方法用了Name註解,如果用了,加入set中
Set<Method> set = new HashSet<Method>();
for(Method m:methods){
boolean mflag=m.isAnnotationPresent(JZMethod.class);
if (mflag){
set.add(m);
}
}
//一次輸出方法註解內容
for (Method m:set){
JZMethod method=(JZMethod)m.getAnnotation(JZMethod.class);
if (method.age()==20){
System.out.println("===人類===");
}
else if(method.age()==500){
System.out.println("===猴子===");
}
else if(method.age()>500){
System.out.println("===妖怪===");
}
System.out.println("外號:"+method.name()+",性別:"+method.sex()+",歲數:"+method.age());
}
System.out.println("===結束====");
}
}
結果輸出:
截止到現在,你應該大致瞭解了Annotation的定義和使用了,當然java也有一些默認的Annotation類型,比如:@Override,@Deprecated,@SuppressWarnings,這裏就不一一介紹了,有興趣的話可以看看相關的資料信息