什麼是註解
註解相當於一種標記,開發工具、編譯器、JVM可以通過反射來了解類和元素有沒有註解,
然後去做出相應的操作。
例如 重寫方法時加上@Override註解,編譯器就會檢查該方法有沒有正確的覆蓋方法
修飾註解的註解:元註解
Retention註解
Retention註解用於限制註解信息保留的階段
@Retention註解有一個屬性value是RetentionPolicy類型的。
RetentionPolicy 有3個枚舉值:SOURCE CLASS RUNTIME
* @RetentinoPolicy(RetentionPolicy.SOURCE) 修飾註解時,該註解的信息只會保留
在源文件中,不會保留在class文件中,也不會被jvm讀取到運行時
* @RetentionPolicy(RetentionPolicy.CLASS) 修飾註解時,該註解的信息會保留在
class文件中,但是不會被jvm讀取
* @RetentionPolicy(RetentionPolicy.RUNTIME) 修飾註解時,該註解的信息會被保留
在class文件中,也會被jvm讀取從而保留到運行時
Target註解
Target註解限定註解適用的類型
Target的value屬性是一個ElementType枚舉類。
枚舉值有7個:
1. ElementType.CONSTRUCTOR —註解可以用於構造器
2. ElementType.FIELD —註解可以用於域聲明
3. ElementType.LOCAL_VARIABLE — 註解可以用於局部變量聲明
4. ElementType.METHOD — 註解可以用於方法聲明
5. ElementType.PACKAGE — 註解可以用於包聲明
6. ElementType.PARAMETER — 註解可以用於參數
7. ElementType.TYPE —註解可以用於類、接口、註解類型、enum聲明
Documented註解
Documented註解表明製作javadoc時,是否將註解信息加入文檔。如果註解在聲明時
使用了@Documented,則在製作javadoc時會將註解信息加入javadoc.
Inherited註解
表明註解是否會被子類繼承。默認情況子類不繼承父類註解。
當一個註解加了@Inherited元註解後,該註解會被使用了該註解的子類繼承
自定義註解的方法
定義註解類型跟一個定義一個接口類似
在interface關鍵字前面加一個@符號
註釋中的每一個方法定義了這個註釋類型的一個元素,
註釋中方法的聲明中一定不能包含參數,也不能拋出異常。
方法的返回值被限定爲基本類型、String、Class、enums、註釋以及這些類型的數組類型
方法可以有缺省值
自定義註解的例子
public @interface RequestForEnhancement{
int id();
String synopsis();
String engineer() default "[unassigned]";
String date(); default "[unimplemented]";
}
註解的用法:
@後面加註解名字,後面再跟上括號,括號中列出這個註釋中的元素以及對應
的值的列表。鍵值對中的值必須是常量。
使用註解的例子
@RequestForEnhancement{id=20142480117,synopsis="Enable time-travel",engineer="Mr.liu",date="4/1/3007"}
標記型註解
如果註解沒有元素,則該註解爲標記型註解(maker)。
標記型註解例子:
public @interface Test{}
在使用標記型註解時,後面的括號可以忽略。
只有一個元素的註解
如果註解只有一個元素,則該元素的名字應該爲value
使用該註解時元素的名字和等號可以省略
用自定義註解實現一個簡單的測試框架
- 定義註解Test
import java.lang.annotation.*;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Test{}
- 在要測試的方法上加@Test註解
public claass TestCase{
@Test
public static void test1(){}
@Test
public static void test2(){
System.out.println("test2");
}
}
import java.lang.reflect.*;
public class TestCaseRun{
public static void main(String args[]){
Class clazz=TestCase.class;
Method[] methods=clazz.getMethods();
for(Method m:methods){
if(m.isAnnotationPresent(Test.class){
try{
m.invoke(null);
}catch(Throwable ex){
System.out.println(ex.getCause());
}
}
}
}
}