記錄一次反射的使用,第一次真正運用到實際工作中,發現反射是真的強大!
寫了一個通用類,主要是便於和 db 的交互操作,使用到了泛型 T 對象,但是有一步需要獲取該對象的屬性 id 值(前提是所有賦值給 T 對象的對象自己都有一個相同類型的 id),再做一點邏輯處理,如果是具體對象來調用這個泛型,則可以正常 getId() 得到該對象的屬性值,但是對於如果是泛型方法里面要通過 T 這個泛型對象來 getId() 出 id 的值,正常是無法獲取到的,解決方法有兩種:
(1)給 T 對象繼承一個統一的父類,在父類里面定義一個 id 屬性,這樣 T 對象就可以點出 id 的屬性值了
(2)通過反射的方式來獲取 id 的屬性值
這里主要介紹第二種:
public Integer getId(T t){ try{ Class<? extends Object> tClass = t.getClass(); //得到所有屬性 Field[] field = tClass.getDeclaredFields(); /** * 這里只需要 id 這個屬性,所以直接取 field[0] 這 * 一個,如果id不是排在第一位,自己取相應的位置, * 如果有需要,可以寫成for循環,遍歷全部屬性 */ //設置可以訪問私有變量 field[0].setAccessible(true); //獲取屬性的名字 String name = field[0].getName(); //將屬性名字的首字母大寫 name = name.replaceFirst(name.substring(0, 1), name.substring(0, 1).toUpperCase()); //整合出 getId() 屬性這個方法 Method m = tClass.getMethod("get"+name); //調用這個整合出來的get方法,強轉成自己需要的類型 Integer id = (Integer)m.invoke(t); //成功通過 T 泛型對象取到具體對象的 id ! return id; }catch(Exception e){ log.info("沒有這個屬性"); return null; } }
如果需要獲取所有的屬性,並且想寫的更靈活,可以再獲取一個屬性的類型,然后寫一個 for 循環,在 for 循環里面對每個屬性再寫一些 if 判斷,對應是什么類型,自己強轉成對應的類型:
for(int i=0;i<field.length;i++){ // 獲取屬性類型 String type = field[i].getGenericType().toString(); if(type.equals("class java.lang.String")){ String value = (String)m.invoke(t); } if(type.equals("class java.lang.Integer")){ Integer value = (Integer)m.invoke(t); } if(type.equals("class java.util.Date")){ Date value = (Date)m.invoke(t); } }
一開始覺得想從泛型 T 對象中取具體的對象的屬性值,感覺有些滑稽,但自己的邏輯處理中如果這一步能夠實現,真的可以簡化很多東西,然后就是帶着這種看似滑稽的想法,嘗試着去做做看,沒想到真的可以實現!
有些東西真的去做了,才會發現多么神奇!