注解:說明程序的刚夺。給計算機看的
注釋:用文字描述程序的。給程序員看的
定義:注解(Annotation)上枕,也叫元數(shù)據(jù)妨马。一種代碼級別的說明挺举。它是JDK1.5及以后版本引入的一個特性杀赢,與類、接口湘纵、枚舉是在同一個層次脂崔。它可以聲明在包、類梧喷、字段砌左、方法、局部變量铺敌、方法參數(shù)等的前面汇歹,用來對這些元素進行說明,注釋偿凭。
概念描述:
①JDK1.5之后的新特性
②說明程序的
③使用注解:@注解名稱作用分類:
①編寫文檔:通過代碼里標識的注解生成文檔【生成文檔doc文檔】
②代碼分析:通過代碼里標識的注解對代碼進行分析【使用反射】
③編譯檢查:通過代碼里標識的注解讓編譯器能夠?qū)崿F(xiàn)基本的編譯檢查【Override】JDK中預(yù)定義的一些注解
①@Override :檢測被該注解標注的方法是否是繼承自父類(接口)的
② @Deprecated:該注解標注的內(nèi)容产弹,表示已過時
③@SuppressWarnings:壓制警告 一般傳遞參數(shù)all @SuppressWarnings("all")-
自定義注解
-
格式:
元注解
public @interface 注解名稱{
屬性列表;
}- 本質(zhì):注解本質(zhì)上就是一個接口,該接口默認繼承Annotation接口
- public interface MyAnno extends java.lang.annotation.Annotation {}
-
屬性:接口中的抽象方法
- 要求:
- 屬性的返回值類型有下列取值
- 基本數(shù)據(jù)類型
- String
- 枚舉
- 注解
- 以上類型的數(shù)組
- 定義了屬性弯囊,在使用時需要給屬性賦值
- 如果定義屬性時痰哨,使用default關(guān)鍵字給屬性默認初始化值,則使用注解時匾嘱,可以不進行屬性的賦值斤斧。
- 如果只有一個屬性需要賦值,并且屬性的名稱是value奄毡,則value可以省略折欠,直接定義值即可。
- 數(shù)組賦值時吼过,值使用{}包裹。如果數(shù)組中只有一個值咪奖,則{}可以省略
- 屬性的返回值類型有下列取值
- 要求:
-
-
元注解:用于描述注解的注解
- @Target:描述注解能夠作用的位置
- ElementType取值:
- TYPE:可以作用于類上
- METHOD:可以作用于方法上
- FIELD:可以作用于成員變量上
- ElementType取值:
- @Retention:描述注解被保留的階段
- @Retention(RetentionPolicy.RUNTIME):當前被描述的注解盗忱,會保留到class字節(jié)碼文件中,并被JVM讀取到
- @Documented:描述注解是否被抽取到api文檔中
- @Inherited:描述注解是否被子類繼承
- @Target:描述注解能夠作用的位置
-
在程序使用(解析)注解:獲取注解中定義的屬性值
- 獲取注解定義的位置的對象 (Class羊赵,Method,Field)
- 獲取指定的注解
- getAnnotation(Class)
//其實就是在內(nèi)存中生成了一個該注解接口的子類實現(xiàn)對象
public class ProImpl implements Pro{
public String className(){
return "cn.itcast.annotation.Demo1";
}
public String methodName(){
return "show";
}
}
- getAnnotation(Class)
- 調(diào)用注解中的抽象方法獲取配置的屬性值
例子
1.注解生成doc文檔
/**
* 注解JavaDoc演示
* @author A
* @version 1.0
* @since 1.5
*/
public class AnnoDemo {
/**
* 計算兩數(shù)的和
* @param a 整數(shù)
* @param b 整數(shù)
* @return 兩數(shù)的和
*/
public int add(int a, int b){
return a + b;
}
}
然后打開命令處理程序 cmd
定位到AnnoDemo.java類文件夾
輸入命令javadoc AnnoDemo.java(javadoc + 要生成文檔java類名)
注意java類的編碼格式不能生成時換成GBK
打開生成的index.html就可以看到像Java官方說明文檔
2.自定義注解
/**
* 屬性的返回值類型有下列取值
* 基本數(shù)據(jù)類型
* String
* 枚舉
* 注解
* 以上類型的數(shù)組
*/
public @interface MyAnno/*注解名*/ {
//基本數(shù)據(jù)類型
int age();
//String
String name() default "張三";
//返回枚舉
Person per();
//返回注解
MyAnno2 anno2();
//數(shù)組
String[] strs();
}
3.元注解
/**
* 元注解:用于描述注解的注解
* @Target:描述注解能夠作用的位置
* ElementType取值:
* TYPE:可以作用于類上
* METHOD:可以作用于方法上
* FIELD:可以作用于成員變量上
* @Retention:描述注解被保留的階段
* @Retention(RetentionPolicy.RUNTIME):前被描述的注解趟佃,會保留到Class字節(jié)碼文件中,并被JVM讀取到
* @Documented:描述注解是否被抽取到API文檔中
* @Inherited:描述注解是否被子類繼承
*/
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented //是否被抽取到API文檔中
@Inherited //是否被子類繼承
public @interface MyAnno3 {
}
4.在程序使用(解析)注解
@Target(ElementType.TYPE)//作用在類上
@Retention(RetentionPolicy.RUNTIME)
public @interface Pro {
String className();
String methodName();
}
@Pro(className = "11111", methodName="2222")
public class Reflect {
public static void main(String[] args) {
//1.解析注解
//1.1獲取該類的字節(jié)碼文件對象
Class<Reflect> reflectClass = Reflect.class;
//2.獲取上邊的注解對象
//其實就是在內(nèi)存中生成一個該注解接口的子類實現(xiàn)對象
Pro an = reflectClass.getAnnotation(Pro.class);
//3.調(diào)用注解對象中定義的抽象方法昧捷,獲取返回值
String className = an.className();
String methodName = an.methodName();
System.out.println(className);
System.out.println(methodName);
}
}
打印className和methodName就會獲取到11111和2222
用注解檢查方法Bug的簡單例子
@Target(ElementType.METHOD)//作用在方法上
@Retention(RetentionPolicy.RUNTIME)
public @interface Check {
}
要檢查的方法加上@Check
@Check
public void add(){
System.out.println("1 + 0 =" + (1 + 0));
}
@Check
public void sub(){
System.out.println("1 - 0 =" + (1 - 0));
}
@Check
public void mul(){
System.out.println("1 * 0 =" + (1 * 0));
}
@Check //錯誤的方法
public void div(){
System.out.println("1 / 0 =" + (1 / 0));
}
簡單的測試框架
/**
* 簡單的測試框架
* <p>
* 當主方法執(zhí)行后闲昭,會自動執(zhí)行被檢查的所有方法(加了Check注解的方法),
* 判斷方法是否有異常靡挥,記錄到文件中
*/
public class TestCheck {
public static void main(String[] args) throws IOException {
Calculator calculator = new Calculator();
Class<? extends Calculator> cls = calculator.getClass();
Method[] methods = cls.getMethods();
int number = 0;
BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));
for (Method method : methods) {
//判斷方法上是否有注解
if (method.isAnnotationPresent(Check.class)) {
try {
method.invoke(calculator);
} catch (Exception e) {
//捕獲記錄異常
//記錄到文件
number++;
bw.write(method.getName() + "方法出現(xiàn)異常");
bw.newLine();
bw.write("異常的名稱:" + e.getCause().getClass().getSimpleName());
bw.newLine();
bw.write("異常的原因:" + e.getCause().getMessage());
bw.newLine();
bw.write("--------------------");
bw.newLine();
}
}
}
bw.write("本次測試一共出現(xiàn)" + number + "異常");
bw.flush();
bw.close();
}
}