前言
實際開發中,泛型使用到處可見。有時候定義接口時,經常使用泛型,而不是指定具體對象,使用泛型的好處很多,特別是代碼複用方面。要獲取類或接口上的泛型類型Class<?>,然後對這個類型進行數據處理,至於怎麼處理,還要看實際的應用場景。本篇講述如何獲取類或接口的泛型類型(參數化類型ParameterizedType
)。
實例
1.定義泛型接口
public interface Response<T> {
void onSuccess(T data);
}
2.定義泛型類
public static class BaseResponse<T> {
}
3.定義測試類和測試方法
測試類
public static class SubResponse extends BaseResponse<Person> {
}
public static class Person {
public String name;
}
測試方法
private static void test(SubResponse subResponse) {
Class<?> clz = getClassT(subResponse, 0);
System.out.println(clz.getSimpleName());
}
private static void test(Response a) {
Class<?> clz = getInterfaceT(a, 0);
System.out.println(clz.getSimpleName());
}
4.調用
test(new Response<Person>() {
@Override
public void onSuccess(Person data) {
}
});
test(new Response<List<Person>>() {
@Override
public void onSuccess(List<Person> data) {
}
});
test(new SubResponse());
5.輸出結果
上面輸出都是Person
這個clz 就是person的Class,有了這個Class,可以做你想做的事情,比如:根據Class實例化對象、或者結合Class把json字符串和xml字符串轉化成具體的bean,然後再返回調用處。
獲取類或接口上的泛型類型T完整代碼
/**
* 獲取接口上的泛型T
*
* @param o 接口
* @param index 泛型索引
*/
public static Class<?> getInterfaceT(Object o, int index) {
Type[] types = o.getClass().getGenericInterfaces();
ParameterizedType parameterizedType = (ParameterizedType) types[index];
Type type = parameterizedType.getActualTypeArguments()[index];
return checkType(type, index);
}
/**
* 獲取類上的泛型T
*
* @param o 接口
* @param index 泛型索引
*/
public static Class<?> getClassT(Object o, int index) {
Type type = o.getClass().getGenericSuperclass();
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type actType = parameterizedType.getActualTypeArguments()[index];
return checkType(actType, index);
} else {
String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException("Expected a Class, ParameterizedType"
+ ", but <" + type + "> is of type " + className);
}
}
private static Class<?> checkType(Type type, int index) {
if (type instanceof Class<?>) {
return (Class<?>) type;
} else if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
Type t = pt.getActualTypeArguments()[index];
return checkType(t, index);
} else {
String className = type == null ? "null" : type.getClass().getName();
throw new IllegalArgumentException("Expected a Class, ParameterizedType"
+ ", but <" + type + "> is of type " + className);
}
}
小結
本篇講述瞭如何獲取類或接口上的泛型類型,實際要靈活使用。上面的Type是Java語言中所有類型的公共父接口。Type有四個子類——ParameterizedType
、 TypeVariable
、GenericArrayType
、WildcardType
。在Gson等框架中有出現,有空的話,大家可以研究一下用法。