概念
Java有五個元注解,自動繼承java.lang.annotation.Annotation。
什么是元注解,可以理解為其他普通注解進行解釋說明
@Target 該注解的使用范圍,限定應用場景。枚舉類 ElemenetType 中
- TYPE:類,接口
- FIELD:字段,枚舉的常量
- METHOD:函數(方法)
- PARAMETER:參數
- CONSTRUCTOR:構造函數
- ANNOTATION_TYPE:注解類型
- LOCAL_VARIABLE:局部變量
- PACKAGE:包
@Retention 該注解的生存周期,相當於時間戳。枚舉類型 RetentionPolicy 中
- SOURCE:在源文件中有效,編譯后會被丟棄(如@Override,@Deprecated)
- CLASS:在class文件中有效,在jvm丟棄
- RUNTIME:在運行時有效,class文件保留,jvm運行時保留(很多框架運用反射調用)
@Documented
javadoc文檔生成工具的使用
@Inherited
允許子類繼承父類中的注解。
@Repeatable
同一種注解可多次使用
作用
- 注釋,解釋,通過代碼的標識元數據生成doc文檔;
- 使用反射,通過代碼標識的元數據對代碼進行分析;
- 編譯檢查,通過代碼標識的元數據讓編譯器進行基本檢查。
實例
定義一個普通的注解,
public @interface Test { }
使用我們自定義的注解
@Test public class Person { @Test private String name; @Test private int age; @Test public void say() { System.out.println("Hello,Java Annotation"); } }
@Target(ElementType.PACKAGE) 注解作用的目標>包
這個注解要理解什么是友好聲明類和包常量,包中有很多的內部訪問的類或常量,就可以統一的放到友好聲明類中,這樣就方便,而且集中管理,減少friendly類到處游走的情況。
可以參考這個 https://www.cnblogs.com/DreamDrive/p/5428573.html
import java.lang.annotation.ElementType; @Target(ElementType.PACKAGE) public @interface Test { }
@Test package test; class Person { private String name; private int age; public void say() { System.out.println("Hello,Java Annotation"); } }
@Target(ElementType.CONSTRUCTOR) 注解作用的目標>構造函數
package test; import java.lang.annotation.ElementType; import java.lang.annotation.Target; @Target(ElementType.CONSTRUCTOR) public @interface Test { }
package test; public class Person { private String name; private int age; @Test public Person() { } public void say() { System.out.println("Hello,Java Annotation"); } }
其他范圍就不一一列舉,都是相同的。
@Retention(RetentionPolicy.RUNTIME) 生存周期
代碼運行時動態獲取注解的信息
package test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.CONSTRUCTOR) @Retention(RetentionPolicy.RUNTIME) public @interface Test { }
package test; public class Person { private String name; private int age;
@Test public Person() { } public void say() { System.out.println("Hello,Java Annotation"); } }
注解的屬性-->成員變量
方法名是成員變量的的名字,變量的類型是他的返回值。
package test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Test { public int age() default 20; public String name() default ""; public String className(); }
package test; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; @Test(age = 15,name = "zhangsan",className = "高三(3)班") public class Person { private String name; private int age; public Person() { } private void say() { System.out.println("Hello,Java Annotation"); } }
既然給了注解,我們要做的工作必然是要提取注解上面的內容,要拿到這些注解就要用到反射。
package test; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; @Test(age = 15,name = "zhangsan",className = "高三(3)班") public class Person {private String name; private int age; public Person() { } private void say() { System.out.println("Hello,Java Annotation"); } public static void main(String[] args) { boolean hasAnnotation = Person.class.isAnnotationPresent(Test.class); if (hasAnnotation) { Test test = Person.class.getAnnotation(Test.class); System.out.println("age:" + test.age()); System.out.println("name:" + test.name()); System.out.println("className:" + test.className()); }
}
}
輸出結果
age:15
name:zhangsan
className:高三(3)班
對於類的屬性和方法,都是同樣的道理。
成員注解
package test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Field { public String name(); }
函數注解
package test; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Method { public String say(); }
Person類
package test; import java.lang.annotation.Annotation; @Test(age = 15,name = "zhangsan",className = "高三(3)班") public class Person { @Field(name = "lisi") private String name; private int age; public Person() { } @Method(say = "hello") private void say() { System.out.println("Hello,Java Annotation"); } public static void main(String[] args) { boolean hasAnnotation = Person.class.isAnnotationPresent(Test.class); if (hasAnnotation) { Test test = Person.class.getAnnotation(Test.class); System.out.println("age:" + test.age()); System.out.println("name:" + test.name()); System.out.println("className:" + test.className()); } try { java.lang.reflect.Field field = Person.class.getDeclaredField("name"); field.setAccessible(true); Field check = field.getAnnotation(Field.class); if (check != null) { System.out.println("check value:" + check.name()); } java.lang.reflect.Method method = Person.class.getDeclaredMethod("say"); if (method != null) { Annotation[] ans = method.getAnnotations(); for (int i = 0; i < ans.length; i++) { System.out.println("method annotation:" + ans[i].annotationType().getSimpleName()); } } } catch (NoSuchFieldException e) { e.printStackTrace(); }catch (Exception e){ e.printStackTrace(); } } }
輸出
age:15 name:zhangsan className:高三(3)班 check value:lisi method annotation:Method
可以看出我們獲取了注解上的值,現在都沒有實際意義,我們可以用注解來做些什么?
這些我沒辦法給出確切答案,只能說根據各人需求去合理利用注解。
實例
注解參數賦值
@Test注解
package 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.FIELD}) public @interface Test { String value(); }
Person類屬性賦值
package test; import org.apache.poi.ss.formula.functions.T; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; public class Person { @Test("zhangsan") private String name; @Test("15") private int age; public Person() { } private void say() { System.out.println("Hello,Java Annotation"); } @Override public String toString() { return "name = " + name + "\n" + "age = " + age; } public static void main(String[] args) { Person person = new Person(); try { //取得成員變量的值 Field field = Person.class.getDeclaredField("name"); //打開權限 field.setAccessible(true); //判斷屬性是否有注解 if (field.isAnnotationPresent(Test.class)) { //獲取屬性上的注解值 Test test = field.getAnnotation(Test.class); String name = test.value(); //賦值 field.set(person,name); } Field field1 = Person.class.getDeclaredField("age"); field1.setAccessible(true); if (field1.isAnnotationPresent(Test.class)) { Test test = field1.getAnnotation(Test.class); int age = Integer.valueOf(test.value()); field1.set(person,age); } System.out.println(person); }catch (Exception e) { e.printStackTrace(); } } }
輸出
name = zhangsan
age = 15
用注解去檢查函數等等。。
lz不善於用語言表達,所以可能有很多人沒看懂,可以看下
一個大佬講解的注解說明(簡單易懂)