Java註解筆記(帶程式碼案例)
1、定義:註解(Annotation),也叫元資料。一種程式碼級別的說明。它是JDK1.5及以後版本引入的一個特性,與類、介面、列舉是在同一個層次。它可以宣告在包、類、欄位、方法、區域性變數、方法引數等的前面,用來對這些元素進行說明,註釋。
2、作用分類:
①編寫文件:通過程式碼裡標識的註解生成文件【生成文件doc文件】
②程式碼分析:通過程式碼裡標識的註解對程式碼進行分析【使用反射】
③編譯檢查:通過程式碼裡標識的註解讓編譯器能夠實現基本的編譯檢查【Override】
3、JDK中預定義的一些註解
* @Override :檢測被該註解標註的方法是否是繼承自父類(介面)的;
* @Deprecated:該註解標註的內容,表示已過時;
* @SuppressWarnings:壓制警告,一般傳遞引數all @SuppressWarnings("all")。
4、自定義註解
* 格式:
元註解
public @interface 註解名稱{
屬性列表;
}
* 本質:註解本質上就是一個介面,該介面預設繼承Annotation介面
* public interface MyAnno extends java.lang.annotation.Annotation {}
* 屬性:介面中的抽象方法
* 要求:
(1)屬性的返回值型別有下列取值
* 基本資料型別
* String
* 列舉
* 註解
* 以上型別的陣列
(2) 定義了屬性,在使用時需要給屬性賦值
a、如果定義屬性時,使用default關鍵字給屬性預設初始化值,則使用註解時,可以不進行屬性的賦值。
b、如果只有一個屬性需要賦值,並且屬性的名稱是value,則value可以省略,直接定義值即可。
c、陣列賦值時,值使用{}包裹。如果陣列中只有一個值,則{}可以省略
(3)元註解:用於描述註解的註解
* @Target:描述註解能夠作用的位置;
ElementType取值:TYPE:可以作用於類上,METHOD:可以作用於方法上,FIELD:可以作用於成員變數上;
* @Retention:描述註解被保留的階段
* @Retention(RetentionPolicy.RUNTIME):當前被描述的註解,會保留到class位元組碼檔案中,並被JVM讀取到
* @Documented:描述註解是否被抽取到api文件中
* @Inherited:描述註解是否被子類繼承
5、案例:簡單測試框架
package com.lidaochen.test; /** * 小明定義的計算器類 */ public class Calculator { //加法 @Check public void add(){ String str = null; str.toString(); 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)); } public void show(){ System.out.println("永無bug..."); } }
package com.lidaochen.test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface Check { }
package com.lidaochen.test; import java.io.BufferedWriter; import java.io.FileWriter; import java.lang.reflect.Method; public class CTestCheck { public static void main(String[] args) throws Exception { // 1、建立計算器物件 Calculator calculator = new Calculator(); // 2、獲取計算器 Class 位元組碼 檔案物件 Class cls = calculator.getClass(); // 3、獲取計算器類的所有方法 Method[] methods = cls.getMethods(); // 出現異常的次數 int number = 0; BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("bug.txt")); for (Method method : methods) { // 判斷方法上是否有 Check 註解 if(method.isAnnotationPresent(Check.class)) { try { // 有 Check 註解 執行方法 method.invoke(calculator); } catch (Exception e) { // 捕獲異常 number++; bufferedWriter.write(method.getName() + "方法出現了異常!"); bufferedWriter.newLine(); bufferedWriter.write("異常名稱:" + e.getCause().getClass().getSimpleName()); bufferedWriter.newLine(); bufferedWriter.write("異常原因:" + e.getCause().getMessage()); bufferedWriter.newLine(); bufferedWriter.write("--------------------------------------"); bufferedWriter.newLine(); } } } bufferedWriter.write("本次測試一共出現了" + number + "次異常!"); bufferedWriter.flush(); bufferedWriter.close(); } }
6、案例:
package com.lidaochen.test; public class CJavaTest { public void eat() { System.out.println("我喜歡吃西瓜!"); } }
package com.lidaochen.test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Pro { String className(); String methodName(); }
package com.lidaochen.test; import java.io.BufferedReader; import java.io.FileReader; import java.lang.reflect.Method; import java.util.Properties; @Pro(className = "com.lidaochen.test.CJavaTest", methodName = "eat") public class CJavaDemo { public static void main(String[] args) throws Exception{ // 1、獲取該類的位元組碼物件 Class cls = CJavaDemo.class; // 2、獲取上邊的註解物件 Pro an = (Pro) cls.getAnnotation(Pro.class); // 3、呼叫註解物件中定義的抽象方法,獲取返回值 String className = an.className(); String methodName = an.methodName(); System.out.println(className); System.out.println(methodName); // 4、載入該類進記憶體 Class mJavaTest = Class.forName(className); // 建立物件 Object obj = mJavaTest.newInstance(); // 獲取方法物件 Method method = mJavaTest.getMethod(methodName); // 執行方法 method.invoke(obj); } }