記錄一次反射的使用,第一次真正運用到實際工作中,發現反射是真的強大!
寫了一個通用類,主要是便於和 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 對象中取具體的對象的屬性值,感覺有些滑稽,但自己的邏輯處理中如果這一步能夠實現,真的可以簡化很多東西,然后就是帶着這種看似滑稽的想法,嘗試着去做做看,沒想到真的可以實現!
有些東西真的去做了,才會發現多么神奇!
