一、java註解
java註解相關的類放在 java.lang.annotation 包下,其主要內容包含4個元註解和其中兩個元註解的枚舉類值,相對比較簡單,從jdk問答即可瞭解
4個元註解:
Documented:指示某一類型的註釋將通過 javadoc 和類似的默認工具進行文檔化。應使用此類型來註釋這些類型的聲明:其註釋會影響由其客戶端註釋的元素的使用。如果類型聲明是用 Documented 來註釋的,則其註釋將成爲註釋元素的公共 API 的一部分。
Inherited:指示註釋類型被自動繼承。如果在註釋類型聲明中存在 Inherited 元註釋,並且用戶在某一類聲明中查詢該註釋類型,同時該類聲明中沒有此類型的註釋,則將在該類的超類中自動查詢該註釋類型。此過程會重複進行,直到找到此類型的註釋或到達了該類層次結構的頂層 (Object) 爲止。如果沒有超類具有該類型的註釋,則查詢將指示當前類沒有這樣的註釋。
注意,如果使用註釋類型註釋類以外的任何事物,此元註釋類型都是無效的。還要注意,此元註釋僅促成從超類繼承註釋;對已實現接口的註釋無效。
Retention:指示註釋類型的註釋要保留多久。如果註釋類型聲明中不存在 Retention 註釋,則保留策略默認爲 RetentionPolicy.CLASS。
只有元註釋類型直接用於註釋時,Target 元註釋纔有效。如果元註釋類型用作另一種註釋類型的成員,則無效。
RetentionPolicy.SOURCE ---------------------------------註解將被編譯器丟棄
RetentionPolicy.CLASS -----------------------------------註解在class文件中可用,但會被VM丟棄
RetentionPolicy.RUNTIME VM-------將在運行期也保留註釋,因此可以通過反射機制讀取註解的信息。
Target: 指示註釋類型所適用的程序元素的種類。如果註釋類型聲明中不存在 Target
元註釋,則聲明的類型可以用在任一程序元素上。如果存在這樣的元註釋,則編譯器強制實施指定的使用限制
ElemenetType.CONSTRUCTOR----------------------------構造器聲明
ElemenetType.FIELD --------------------------------------域聲明(包括 enum 實例)
ElemenetType.LOCAL_VARIABLE------------------------- 局部變量聲明
ElemenetType.METHOD ----------------------------------方法聲明
ElemenetType.PACKAGE --------------------------------- 包聲明
ElemenetType.PARAMETER ------------------------------參數聲明
ElemenetType.TYPE--------------------------------------- 類,接口(包括註解類型)或enum聲明
二、註解例子
該例子有3個文件:註解類Annotation_1、使用註解類UseAnnotation、解析註解類ParseAnnotation
package com.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Annotation_1 { String name(); int id() default 0; Class gid(); }
package com.annotation; import java.lang.reflect.Method; @Annotation_1(name="useAnnotation", id=1, gid=Long.class) public class UseAnnotation { @Annotation_1(name="a", gid=Integer.class) public int a; @Annotation_1(name="constractor_method", gid=Method.class) public UseAnnotation(){ } @Annotation_1(name="getA", id=2, gid=Method.class) public int getA(){ return this.a; } @Annotation_1(name="setA", id=2, gid=Method.class) public void setA(int a){ this.a = a; } }
package com.annotation; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ParseAnnotation { /** * 解析類的註解 * @throws ClassNotFoundException */ public void parseClass() throws ClassNotFoundException{ // Class clazz = Class.forName("com.annotation.UseAnnotation"); Annotation[] as = UseAnnotation.class.getAnnotations(); for(Annotation a: as){ Annotation_1 a1 = (Annotation_1)a; System.out.println("CLASS: name=" + a1.name() + ", id=" + a1.id() + ", gid=" + a1.gid()); } } /** * 解析方法的註解 */ public void parseMethod(){ Method[] methods = UseAnnotation.class.getMethods(); this.parse(methods); } /** * 解析成員變量的註解 */ public void parseField(){ Field[] fields = UseAnnotation.class.getFields(); this.parse(fields); } private <T extends AccessibleObject> void parse(T[] ts){ for(T t: ts){ Annotation annotation = t.getAnnotation(Annotation_1.class); if(annotation == null){ System.out.println(t.getClass().getName() + " do not have Annotation_1"); }else{ Annotation_1 a1 = (Annotation_1)annotation; System.out.println(t.getClass().getName() + ": name=" + a1.name() + ", id=" + a1.id() + ", gid=" + a1.gid()); } } } public static void main(String[] args) throws ClassNotFoundException { ParseAnnotation pa = new ParseAnnotation(); pa.parseClass(); pa.parseMethod(); pa.parseField(); } }
三、利用註解和反射將map轉化成bean
該例子使用註解和反射的技術將map類型轉化成對應的bean
主要包含4個類:註解類PojoAnnotation、bean類User、轉換工具類PojoMappingUtil、測試類PojoTest
package com.annotation.userdemo; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) public @interface PojoAnnotation { String name(); }
package com.annotation.userdemo; public class User { @PojoAnnotation(name="NAME") private String name; @PojoAnnotation(name="AGE") private Integer age; public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "User [name=" + name + ", age=" + age + "]"; } }
package com.annotation.userdemo; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Map; public class PojoMappingUtil { /** * 將map中key與註解一致的值放到對應成員變量中 */ public static <T> T parsePoje(Map<String, Object> map, Class<T> clazz) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException{ T t = clazz.newInstance(); Field[] fields = clazz.getDeclaredFields(); for(Field field : fields){ PojoAnnotation pojoAnnotation = field.getAnnotation(PojoAnnotation.class); if(pojoAnnotation != null){ Object o = map.get(pojoAnnotation.name()); if(o != null){ String fieldName = field.getName(); Method method = clazz.getMethod("set" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1), o.getClass()); method.invoke(t, o); } } } return t; } }
package com.annotation.userdemo; import java.lang.reflect.InvocationTargetException; import java.util.HashMap; import java.util.Map; public class PojoTest { public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException { Map<String, Object> map = new HashMap<String , Object>(); map.put("NAME", "小明"); map.put("AGE", 10); User user = PojoMappingUtil.parsePoje(map, User.class); System.out.println(user); } }