標籤:反射 java 註解 物件導向 jvm
轉載請註明出處:http://blog.csdn.net/lhy_ycu/article/details/45295947
一、前言
Java中的註解Annotation運用到很多方面,比如之前講的單元測試中的@Test、Spring、SpringMVC還有其他架構等等。Java本身內建的註解也有一些,比如:@Override(子類要重寫/覆寫父類的對應方法)、@Deprecated(表示方法不建議被使用)、@SuppressWarnings(抑制警告)等等。當然,我們也可以自訂一些自己需要的註解(通常可以加在包,類,欄位,方法,方法的參數以及局部變數上),這需要Java提供的四種元註解來負責完成我們的自訂註解功能。總體來說,註解比較還是簡單的。下面先瞭解一下這四種元註解:
二、四種元註解(來源網路)
(一) @Target
@Target 表示該註解用於什麼地方,可取的值包括:
ElemenetType.CONSTRUCTOR 構造器聲明
ElemenetType.FIELD 欄位聲明(包括 enum 執行個體)
ElemenetType.LOCAL_VARIABLE 局部變數聲明
ElemenetType.METHOD 方法聲明
ElemenetType.PACKAGE 包聲明
ElemenetType.PARAMETER 參數聲明
ElemenetType.TYPE 類,介面(包括註解類型)或enum聲明
ElementType.ANNOTATION_TYPE 註解
(二) @Retention
@Retention 表示在什麼層級儲存該註解資訊。可選的 RetentionPolicy 參數包括:
RetentionPolicy.SOURCE 註解將被編譯器丟棄
RetentionPolicy.CLASS 註解在class檔案中可用,但會被VM丟棄
RetentionPolicy.RUNTIME JVM將在運行期也保留注釋,因此可以通過反射機制讀取註解的資訊。
(三) @Documented
@Documented 將此註解包含在 javadoc 中
(四)@Inherited
@Inherited 允許子類繼承父類中的註解
三、執行個體說明1) 作用在類上的註解
// 編譯器將把註解資訊記錄在class檔案中,當運行Java程式時JVM會保留註解,因此可以通過反射機制來讀取註解的資訊。@Retention(RetentionPolicy.RUNTIME)// 註解作用在類上面@Target(ElementType.TYPE)public @interface ClassName {// 聲明預設值String name() default "豆豆";// 特殊的值String value();}
2) 作用在屬性(欄位)上的註解
@Retention(RetentionPolicy.RUNTIME)// 註解作用在屬性(欄位)上@Target(ElementType.FIELD)public @interface FieldName {String value();}
3)作用在方法上的註解
@Retention(RetentionPolicy.RUNTIME)// 注釋作用在方法上@Target(ElementType.METHOD)public @interface MethodName {String value();Class<?> type();}
4)執行個體示範
import java.lang.reflect.Field;import java.lang.reflect.Method;/** * @author [*昨日重現*] [email protected] * @since version 1.0 * @datetime 2015年4月27日 上午12:57:03 */// 指定用的是哪個自訂註解的類,若把name去掉,則name預設為:豆豆@ClassName(name = "實體", value = "使用者")public class User {@FieldName("姓名")private String name;@FieldName("性別")private String sex;public String getName() {return name;}@MethodName(type = java.lang.String.class, value = "王五")public void setName(String name) {this.name = name;}public String getSex() {return sex;}@MethodName(type = java.lang.String.class, value = "男")public void setSex(String sex) {this.sex = sex;}@Overridepublic String toString() {return "User [name=" + name + ", sex=" + sex + "]";}public static void main(String[] args) throws Exception {Class<?> c1 = Class.forName("com.leo.annotation.User");// Class<?> c1 = Student.class;// 一: 擷取類上的註解資訊// 如果該元素的指定註解類型的註解存在於此對象上,則返回這些注釋,否則返回 nullClassName cn = c1.getAnnotation(ClassName.class);System.out.println(cn.name() + " ," + cn.value());System.out.println("\n=============================");// 二:擷取屬性(欄位)上的註解資訊Field f1 = c1.getDeclaredField("sex");f1.setAccessible(true);FieldName fn = f1.getAnnotation(FieldName.class);System.out.println(fn.value());// Field[] fields = c1.getDeclaredFields();// for (Field field : fields) {// field.setAccessible(true);// FieldName fn = field.getAnnotation(FieldName.class);// if (fn != null) {// System.out.println(fn.value());// }// }// 三:擷取方法上的註解資訊Method[] methods = c1.getDeclaredMethods();User obj = (User) c1.newInstance();for (Method method : methods) {System.out.println("方法名:" + method.getName());// 檢查方法上面是否有AnnotationMethodName mn = method.getAnnotation(MethodName.class);if (mn != null) {// 回調賦值。第一個參數為目標對象,第二個參數為被訪問的方法實參method.invoke(obj, mn.value());}}System.out.println(obj.getName() + " ," + obj.getSex());}}
四、總結
1)注意:註解不是注釋。註解提供的是實現程式功能的重要組成部分,而注釋提供代碼功能的說明。
2)註解使得Java原始碼中不但可以包含功能性的實現代碼,還可以添加中繼資料。
Java學習系列(二十一)Java物件導向之註解詳解