利用註解完成對成員變量的自動初始化。應用場景,某應用分爲不少個模塊,爲了簡化後續開發人員配置新模塊的工做,使項目維護更爲容易,運用註解來對模塊進行初始化。簡單修改後能夠成爲相似ButterKnife
的工具。java
區別在於ButterKnife
的註解類型是@Retention(RetentionPolicy.SOURCE)
的,即源代碼編譯階段發揮做用的註解,編譯完後就丟棄了。而我用的是@Retention(RetentionPolicy.RUNTIME)
,也是書上用到的,即運行時的再生效的註解,使用反射來完成註解所要達成的目標,有必定的性能損耗。函數
先來看ModuleEntry
類,每一個該類對象表示一個模塊。工具
public class ModuleEntry { int id; String name; String des; public ModuleEntry(int id, String name, String des) { this.id = id; this.name = name; this.des = des; } }
@Target(ElementType.FIELD) @Retention(RetentionPolicy.SOURCE) public @interface Module { int id(); //String value();//注意註解中名爲value的元素,若是應用該註解時,value元素是惟一須要賦值的元素,那麼只需在括號內給出value元素所需的值便可 String moduleName() default ""; String moduleDes() default ""; }
用以標識包含ModuleEntry
的對象的類,咱們將對這個類中的帶有Module
註解的元素進行自動初始化。性能
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface ModuleSet { String value();//其實這裏的value沒有什麼意義,是爲了表示一下value元素的特殊,這點稍後會看到 }
先看main
函數,我最終想要實現的效果應該是其中的ModuleEntry
對象都能根據註解本身初始化。this
class Activity{} @ModuleSet("Main") class MainActivity extends Activity{ @Module(id = 0, moduleName = "模塊管理", moduleDes = "對模塊進行管理") ModuleEntry mManagerModule; @Module(id = 1, moduleName = "校園網", moduleDes = "校園網管理") ModuleEntry mSeunetModule; ModuleEntry mOtherModule; public MainActivity(){ ModuleHelper.configureModule(this); } } public class Main{ public static void main(String[] args){ MainActivity mainActivity = new MainActivity(); System.out.println(mainActivity.mManagerModule.des); //NullPointerException,由於mOtherModule沒有添加註解,不會被自動初始化 //System.out.println(mainActivity.mOtherModule.des); } }
而自動初始化是由ModuleHelper
來完成的。code
public class ModuleHelper { public static void configureModule(Activity activity){ //輸出傳入對象類型 System.out.println(activity.getClass()); //查看其是否添加了ModuleSet註解並獲取註解 System.out.println(activity.getClass().isAnnotationPresent(ModuleSet.class)); ModuleSet moduleSetAnnotation = activity.getClass().getAnnotation(ModuleSet.class); //必須添加了該註解的類才能使用這個方法,不然不作任何操做 if (moduleSetAnnotation == null)return; //遍歷全部的域 for (Field field : activity.getClass().getDeclaredFields()){ Module module = field.getAnnotation(Module.class); //若是沒有模塊註解,或者其類型不是模塊實體,則跳過 if(module == null || field.getType() != ModuleEntry.class)continue; //對全部的知足條件的Field,輸出模塊對應的名字和描述 System.out.println(module.moduleName() + " " + module.moduleDes()); System.out.println(field.getName()); //生成模塊條目 ModuleEntry moduleEntry = new ModuleEntry(module.id(),module.moduleName(),module.moduleDes()); try { field.setAccessible(true); //使用set函數能夠爲當前的field實際表明的對象進行賦值,若是是static對象則能夠把第一個參數置爲null field.set(activity,moduleEntry); //使用get函數能夠得到這個對象 //ModuleEntry moduleEntry0 = (ModuleEntry) field.get(activity); } catch (IllegalAccessException e) { e.printStackTrace(); } } } } /**Output class com.note.MainActivity true 模塊管理 對模塊進行管理 mManagerModule 校園網 校園網管理 mSeunetModule 對模塊進行管理 */