Java 反射 API 中的 java.lang.reflect.Type 體系是泛型類型信息在運行期的載體。由於擦除機制,Class 無法攜帶泛型參數,JDK 引入 ParameterizedType、GenericArrayType、TypeVariable、WildcardType 四大子類型完整表達泛型簽名。本文系統講解四大類型結構、獲取方法、實戰解析邏輯與框架應用場景。
java.lang.reflect.Type (介面) ├─ Class // 原始類型、原始類、基本類型、數組類型(擦除後) ├─ ParameterizedType // 參數化類型:List, Map ├─ GenericArrayType // 泛型數組類型:T[], List [] ├─ TypeVariable // 類型變量:T, K, V └─ WildcardType // 通配符類型:?, ? extends Number, ? super Integer
表示:帶類型參數的類/介面,如 Map。
核心方法:
Type[] getActualTypeArguments():返回最外層類型參數的實際類型。Map> → [String, List] (不遞歸展開內層 Integer)。Type getRawType():返回原始類型(Class),如 Map.class。Type getOwnerType():返回外部類類型(內部類場景),頂層類返回 null。表示:元素類型為參數化類型/類型變量的數組,如 T[]、List。
核心方法:
Type getGenericComponentType():返回最左側維度的元素類型。T[][] → T[] (GenericArrayType);List[] → List (ParameterizedType)。注意:Java 不允許 new List 創建泛型數組,但字段/參數/返回值可聲明泛型數組類型。
表示:泛型聲明處的類型參數,如 class Box 中的 T、void 中的 T。
核心方法:
Type[] getBounds():返回上界類型數組。 → [Number, Comparable]。 → [Object]。String getName():返回類型變量名稱(如 "T")。GenericDeclaration getGenericDeclaration():返回聲明該類型變量的泛型實體(類/方法/介面)。表示:?、? extends Bound、? super Bound。
核心方法:
Type[] getUpperBounds():返回上界數組。? extends Number → [Number];? → [Object]。Type[] getLowerBounds():返回下界數組。? super Integer → [Integer];無下界 → 空數組。public class GenericSignatureResolver {
public static void resolveMethod(Method method) {
System.out.println("=== " + method + " ===");
// 1. 返回類型
Type retType = method.getGenericReturnType();
printType("Return", retType, 0);
// 2. 參數類型
Type[] paramTypes = method.getGenericParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
printType("Param[" + i + "]", paramTypes[i], 0);
}
}
private static void printType(String prefix, Type type, int indent) {
String pad = " ".repeat(indent);
if (type instanceof Class) {
System.out.println(pad + prefix + ": Class = " + type);
} else if (type instanceof ParameterizedType) {
ParameterizedType pt = (ParameterizedType) type;
System.out.println(pad + prefix + ": ParameterizedType");
System.out.println(pad + " RawType = " + pt.getRawType());
System.out.println(pad + " OwnerType = " + pt.getOwnerType());
Type[] args = pt.getActualTypeArguments();
for (int i = 0; i < args.length; i++) {
printType("Arg[" + i + "]", args[i], indent + 1);
}
} else if (type instanceof GenericArrayType) {
GenericArrayType gat = (GenericArrayType) type;
System.out.println(pad + prefix + ": GenericArrayType");
printType("Component", gat.getGenericComponentType(), indent + 1);
} else if (type instanceof TypeVariable) {
TypeVariable> tv = (TypeVariable>) type;
System.out.println(pad + prefix + ": TypeVariable = " + tv.getName());
System.out.println(pad + " Bounds = " + Arrays.toString(tv.getBounds()));
} else if (type instanceof WildcardType) {
WildcardType wt = (WildcardType) type;
System.out.println(pad + prefix + ": WildcardType");
System.out.println(pad + " UpperBounds = " + Arrays.toString(wt.getUpperBounds()));
System.out.println(pad + " LowerBounds = " + Arrays.toString(wt.getLowerBounds()));
}
}
}
List.class == List.class == List.class ,同一個 Class 對象。Signature 屬性中保留完整泛型簽名,反射 API 讀取並構建 Type 對象圖。TypeReference (TypeToken) 獲取 List 完整類型,正確反序列化泛型集合。List,提取 Entity 類構建結果映射。ResolvableType 封裝 Type 體系,解析 @Autowired List 實際泛型參數。| 陷阱 | 原因 | 對策 |
|---|---|---|
直接用 method.getReturnType() | 返回 Class,丟失泛型參數 | 必須用 getGenericReturnType() |
| ParameterizedType.getActualTypeArguments() 遞歸期望 | 僅返回最外層,內層仍是 ParameterizedType | 遞歸調用 printType 逐層展開 |
| TypeVariable.getBounds() 返回 Object | 無界聲明 隱含上界 Object | 判斷 bounds.length==1 && bounds[0]==Object.class 視為無界 |
| WildcardType 上下界同時存在 | 語法不允許 ? extends A super B | 上下界互斥,檢查數組長度決定類型 |
泛型數組創建 new T[10] | 擦除後類型不安全,編譯器禁止 | 用 List 或 (T[]) new Object[10](慎用) |