使用@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註解就只有一個參數成員。數組
簡單的自定義註解和使用註解實例: bash
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,用於描述註解的使用範圍(方法、構造方法、成員變量、枚舉值) app
取值(ElementType)有:ide
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
參考:www.cnblogs.com/gmq-sh/p/47…
註解(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
@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)
用法和上面的講述的同樣,之不過建立的註解型的引用變量指向的是 "標記對應方法的註解"
複製代碼