二、 ParameterizedType 參數化的類型,顧名思義,就是給一個類型傳遞了類型參數,例 List<Contract> List接口被傳遞了Contract類型參數,那麼類型List<Contract>就是ParameterizedType,它可以做屬性的類型,做方法參數或傳回值的類型,也可以做泛型聲明的上邊界。 例如 public class GenericClass<T extends List<Contract>>裡的List<Contract>。由于泛型聲明可以聲明多個泛型參數,是以,參數化的類型也可以傳入多個類型參數,多個類型參數用,隔開。例如著名的Map定義的泛型參數是K和V 可以傳入Map<String,Contract>等等.如果屬性或方法參數聲明的資料給類型傳遞了類型參數,則field.getGenericType method.getGenericParameterType傳回Type 就是 instanceof ParameterizedType. ptype.getActualTypeArguments() :Type[]傳回每個傳入的類型參數,傳回值的長度取決于泛型聲明時聲明了幾個形式泛型參數。本文提出的問題便是基于這一點來嘗試解決的。ptype.getRawType() type傳回的是<>外的類型 即接收類型參數的類型,如List,Map.
三、WildcardType 這種類型用來處理參數化類型裡,對類型參數範圍的描述。例如一個方法的泛型參數是 Map<? extends Number,? super Contract>,此時 <> 裡用逗号隔開兩個對象都是WildcardType的執行個體。對每一個WildcardType對象(驗證type instanceof WildcardType==true) wtype.getUpperBounds():Type[]傳回上邊界類型(預設是Object.class),wtype.getLowerBounds():Type[]傳回下邊界類型。
說了這麼多,邏輯太繞了,本來就很難說清楚。隻有多測試多使用才能體會到。下面給一個我寫的方法,這個方法用來通路一個Collection接口類型的Field,假定該Field使用了泛型,然後傳回Collection的類型參數具體是什麼,即傳回客戶類指定的集合元素的類型。注意,的确隻能在運作時才能确定具體類型,本方法隻能獲得泛型的邊界,然後用上邊界類型來構造對象。如果一個使用了泛型的屬性剛好就像List<Contract>一樣,那麼讀取到Contract.class是輕而易舉的,因為這個泛型參數的邊界是固定的。
public Class getGenericTypeBounds(Field field)
throws TypeResolveException{
Type type = field.getGenericType();
if(type instanceof Class){
throw new TypeResolveException(field.getDeclaringClass().getName()+"屬性"
+field.getName()+" 沒有使用泛型或者 使用了rawtype但是沒有指定泛型實參。");
}
else if(type instanceof GenericArrayType){
type = ((GenericArrayType)type).getGenericComponentType();
}
else if(type instanceof TypeVariable<?>){
type = ((TypeVariable<?>)type).getBounds()[0];
}
else if(type instanceof ParameterizedType){
ParameterizedType ptype = (ParameterizedType)type;
Type[] types = ptype.getActualTypeArguments();
if(types==null || types.length==0){
throw new TypeResolveException(field.getDeclaringClass().getName()+"的集合屬性"
+field.getName()+" 所引用的泛型類型沒有指定泛型實參取值。");
}
if(types.length>1){
throw new TypeResolveException(field.getDeclaringClass().getName()+"的集合屬性"
+field.getName()+" 所引用的泛型類型 指定的泛型實參取值多于1個。");
}
type = ptype.getActualTypeArguments()[0];//隻有這個方法的傳回值才可能是 WildcardType
}
while(!(type instanceof Class)){
if(type instanceof WildcardType){
type = ((WildcardType)type).getUpperBounds()[0];
}
else if(type instanceof TypeVariable<?>){
type = ((TypeVariable<?>)type).getBounds()[0];
}
else if(type instanceof ParameterizedType){
ParameterizedType ptype = (ParameterizedType)type;
Type[] types = ptype.getActualTypeArguments();
if(types==null||types.length==0){
return Object.class;
}
if(types.length>1){
throw new TypeResolveException(field.getDeclaringClass().getName()+"的集合屬性"
+field.getName()+"引用到的泛型"+ptype+"的實參數量多于1個");
}
type = ptype.getActualTypeArguments()[0];
}
else if(type instanceof GenericArrayType ){
type = ((GenericArrayType)type).getGenericComponentType();
}
}
return (Class)type;
}