1、RetentionPolicy.SOURCE:註解只保留在源文件,當Java文件編譯成class文件的時候,註解被遺棄;
2、RetentionPolicy.CLASS:註解被保留到class文件,但jvm加載class文件時候被遺棄,這是默認的生命週期;
3、RetentionPolicy.RUNTIME:註解不僅被保存到class文件中,jvm加載class文件之後,仍然存在;
這3個生命週期分別對應於:Java源文件(.java文件)--->.class文件--->內存中的字節碼。
那怎麼來選擇合適的註解生命週期呢?
首先要明確生命週期長度SOURCE<CLASS<RUNTIME,所以前者能作用的地方後者一定也能作用。一般如果需要在運行時去動態獲取註解信息,那隻能用RUNTIME註解;如果要在編譯時進行一些預處理操作,比如生成一些輔助代碼(如ButterKnife),就用CLASS註解;如果只是做一些檢查性的操作,比如@Override和@SuppressWarnings,則可選用SOURCE註解。
下面來介紹下運行時註解的簡單運用。
獲取註解
你需要通過反射來獲取運行時註解,可以從Package、Class、Field、Method...上面獲取,基本方法都一樣,幾個常見的方法如下:
/** * 獲取指定類型的註解*/public <A extends Annotation> A getAnnotation(Class<A> annotationType);/** * 獲取所有註解,如果有的話*/public Annotation[] getAnnotations();/** * 獲取所有註解,忽略繼承的註解*/public Annotation[] getDeclaredAnnotations();/** * 指定註解是否存在該元素上,如果有則返回true,否則false */public Boolean isAnnotationPresent(Class<? extends Annotation> annotationType);/** * 獲取Method中參數的所有註解*/public Annotation[][] getParameterAnnotations();
要使用這些函數必須先通過反射獲取到對應的元素:Class、Field、Method等。
自定義註解
來看下自定義註解的簡單使用方式,這裡先定義3個運行時註解:
// 適用類、接口(包括註解類型)或枚舉@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ClassInfo { String value(); } // 適用field屬性,也包括enum常量@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface FieldInfo { int[] value(); } // 適用方法@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MethodInfo { String name() default "long"; String data(); int age() default 27; }這3個註解分別適用於不同的元素,並都帶有不同的屬性,在使用註解是需要設置這些屬性值。
再定義一個測試類來使用這些註解:
/** * 測試運行時註解*/@ClassInfo("Test Class") public class TestRuntimeAnnotation {@FieldInfo(value = {1, 2}) public String fieldInfo = "FiledInfo";@FieldInfo(value = {10086}) public int i = 100;@MethodInfo(name = "BlueBird", data = "Big") public static String getMethodInfo() {return TestRuntimeAnnotation.class.getSimpleName();}}使用還是很簡單的,最後來看怎麼在代碼中獲取註解信息:
/** * 測試運行時註解*/private void _testRuntimeAnnotation() {StringBuffer sb = new StringBuffer();Class<?> cls = TestRuntimeAnnotation.class;Constructor<?>[] constructors = cls.getConstructors();// 獲取指定類型的註解sb.append("Class註解:").append("/n");ClassInfo classInfo = cls.getAnnotation(ClassInfo.class);if (classInfo != null) {sb.append(Modifier.toString(cls.getModifiers())).append(" ") .append(cls.getSimpleName()).append("/n");sb.append("註解值: ").append(classInfo.value()).append("/n/n");}sb.append("Field註解:").append("/n");Field[] fields = cls.getDeclaredFields();for (Field field : fields) {FieldInfo fieldInfo = field.getAnnotation(FieldInfo.class);if (fieldInfo != null) {sb.append(Modifier.toString(field.getModifiers())).append(" ") .append(field.getType().getSimpleName()).append(" ") .append(field.getName()).append("/n");sb.append("註解值: ").append(Arrays.toString(fieldInfo.value())).append("/n/n");}}sb.append("Method註解:").append("/n");Method[] methods = cls.getDeclaredMethods();for (Method method : methods) {MethodInfo methodInfo = method.getAnnotation(MethodInfo.class);if (methodInfo != null) {sb.append(Modifier.toString(method.getModifiers())).append(" ") .append(method.getReturnType().getSimpleName()).append(" ") .append(method.getName()).append("/n");sb.append("註解值: ").append("/n");sb.append("name: ").append(methodInfo.name()).append("/n");sb.append("data: ").append(methodInfo.data()).append("/n");sb.append("age: ").append(methodInfo.age()).append("/n");}}System.out.print(sb.toString());}所做的操作都是通過反射獲取對應元素,再獲取元素上面的註解,最後得到註解的屬性值。
看一下輸出情況,這裡我直接顯示在手機上:
總結
以上就是本文關於java語言註解基礎概念詳解的全部內容,希望對大家有所幫助。感興趣的朋友可以繼續參閱本站其他相關專題,如有不足之處,歡迎留言指出。感謝朋友們對本站的支持!