四、Java反射
57.什麼是反射?
58.什麼是 java 序列化?什麼情況下需要序列化?
59.動態代理是什麼?有哪些應用?
60.怎麼實現動態代理?
Java通過指定類對應的Class對象,程序可以獲得該類裏包括的所有Field,不管該Field使用private修飾,還是使用public修飾。獲得了Field對象後,就可以很容易的獲得該Field的數據類型,例如,下面的代碼便是獲得該Field對象foeld的類型: Class<?> type = field.getType();
但是通過這種方式只對普通類型的Field有效,如果該Field的類型是有泛型限制的類型,如Map<String,Integer>類型,則不能準確得到該Field的泛型參數。
爲了獲得指定Field的泛型類型,應該使用如下方法來獲取指定Field的泛型類型:
Type type = field.getGenericType();
然後將Type對象強制類型轉換成ParameterizedType對象,ParameterizedType代表被參數化的類型,也就是增加了泛型限制的類型,ParameterizedType類提供了兩個方法:
getRawType();//返回被泛型限制的類型;
getActualTypeArguments();//返回泛型參數類型。
下面,我們來看一個完整的例子,方便大家掌握:
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
public class GenericTest {
private Map<String, Integer> map = new HashMap<String, Integer>();
public static void main(String[] args) throws SecurityException,
NoSuchFieldException {
// 獲取Class實例
Class<GenericTest> class1 = GenericTest.class;
// 根據屬性名取得該屬性對應的Field對象
Field mapField = class1.getDeclaredField("map");
// 示範第一個方法:直接通過getType()取出Field的類型,只對普通類型的Field有效
Class<?> class2 = mapField.getType();
// 輸出查看
System.out.println("屬性名爲map的屬性類型爲:" + class2);
// 示範第二種方法:
Type mapMainType = mapField.getGenericType();
// 爲了確保安全轉換,使用instanceof
if (mapMainType instanceof ParameterizedType) {
// 執行強制類型轉換
ParameterizedType parameterizedType = (ParameterizedType) mapMainType;
// 獲取基本類型信息,即Map
Type basicType = parameterizedType.getRawType();
System.out.println("基本類型爲:" + basicType);
// 獲取泛型類型的泛型參數
Type[] types = parameterizedType.getActualTypeArguments();
for (int i = 0; i < types.length; i++) {
System.out.println("第" + (i + 1) + "個泛型類型是:" + types[i]);
}
} else {
System.out.println("獲取泛型類型出錯!");
}
}
}
Java反射獲取泛型工具類
import java.lang.reflect.Field; import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List;
/**
* 泛型工具類
*/
public class GenericsUtils {
/**
* 通過反射,獲得指定類的父類的泛型參數的實際類型. 如BuyerServiceBean extends DaoSupport<Buyer>
*
* @param clazz clazz 需要反射的類,該類必須繼承範型父類
* @param index 泛型參數所在索引,從0開始.
* @return 範型參數的實際類型, 如果沒有實現ParameterizedType接口,即不支持泛型,所以直接返回
* <code>Object.class</code>
*/
@SuppressWarnings("unchecked")
public static Class getSuperClassGenricType(Class clazz, int index) {
}
未完待續