从给定的Type对象中提取泛型类型。
/* * $Id: GenericsUtils.java 20321 2010-11-24 15:21:24Z dfeist $ * -------------------------------------------------------------------------------------- * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. *///来自 N o w J a v a . c o m - 时 代 Java import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; import java.lang.reflect.WildcardType; import java.util.Collection; import java.util.Map; public class Main{ /** * Extract the generic type from the given Type object. * * @param methodParam the method parameter specification * @param type the Type to check * @param source the source collection/map Class<?> that we check * @param typeIndex the index of the actual type argument * @param nestingLevel the nesting level of the target type * @param currentLevel the current nested level * @return the generic type as Class, or <code>null</code> if none */ private static Class<?> extractType(MethodParameter methodParam, Type type, Class<?> source, int typeIndex, int nestingLevel, int currentLevel) { Type resolvedType = type; if (type instanceof TypeVariable<?> && methodParam != null && methodParam.typeVariableMap != null) { Type mappedType = methodParam.typeVariableMap.get(type); if (mappedType != null) { /* nowjava.com */ resolvedType = mappedType; } } if (resolvedType instanceof ParameterizedType) { return extractTypeFromParameterizedType(methodParam, (ParameterizedType) resolvedType, source, typeIndex, nestingLevel, currentLevel); } else if (resolvedType instanceof Class<?>) { Class<?> resolvedClass = (Class<?>) resolvedType; return extractTypeFromClass(methodParam, resolvedClass, source, typeIndex, nestingLevel, currentLevel); } else { return null; } } /** * Extract the generic type from the given ParameterizedType object. * * @param methodParam the method parameter specification * @param ptype the ParameterizedType to check * @param source the expected raw source type (can be <code>null</code>) * @param typeIndex the index of the actual type argument * @param nestingLevel the nesting level of the target type * @param currentLevel the current nested level * @return the generic type as Class, or <code>null</code> if none */ private static Class<?> extractTypeFromParameterizedType( MethodParameter methodParam, ParameterizedType ptype, Class<?> source, int typeIndex, int nestingLevel, int currentLevel) { if (!(ptype.getRawType() instanceof Class<?>)) { return null; } Class<?> rawType = (Class<?>) ptype.getRawType(); Type[] paramTypes = ptype.getActualTypeArguments(); if (nestingLevel - currentLevel > 0) { int nextLevel = currentLevel + 1; Integer currentTypeIndex = (methodParam != null ? methodParam .getTypeIndexForLevel(nextLevel) : null); // Default is last parameter type: Collection element or Map value. int indexToUse = (currentTypeIndex != null ? currentTypeIndex : paramTypes.length - 1); Type paramType = paramTypes[indexToUse]; return extractType(methodParam, paramType, source, typeIndex, nestingLevel, nextLevel); } if (source != null && !source.isAssignableFrom(rawType)) { return null; } Class<?> fromSuperclassOrInterface = extractTypeFromClass( methodParam, rawType, source, typeIndex, nestingLevel, currentLevel); if (fromSuperclassOrInterface != null) { return fromSuperclassOrInterface; } if (paramTypes == null || typeIndex >= paramTypes.length) { return null; } Type paramType = paramTypes[typeIndex]; if (paramType instanceof TypeVariable<?> && methodParam != null && methodParam.typeVariableMap != null) { Type mappedType = methodParam.typeVariableMap.get(paramType); if (mappedType != null) { paramType = mappedType; } } if (paramType instanceof WildcardType) { WildcardType wildcardType = (WildcardType) paramType; Type[] upperBounds = wildcardType.getUpperBounds(); if (upperBounds != null && upperBounds.length > 0 && !Object.class.equals(upperBounds[0])) { paramType = upperBounds[0]; } else { Type[] lowerBounds = wildcardType.getLowerBounds(); if (lowerBounds != null && lowerBounds.length > 0 && !Object.class.equals(lowerBounds[0])) { paramType = lowerBounds[0]; } } } if (paramType instanceof ParameterizedType) { paramType = ((ParameterizedType) paramType).getRawType(); } if (paramType instanceof GenericArrayType) { // A generic array type... Let's turn it into a straight array type if possible. Type compType = ((GenericArrayType) paramType) .getGenericComponentType(); if (compType instanceof Class<?>) { Class<?> compClass = (Class<?>) compType; return Array.newInstance(compClass, 0).getClass(); } } else if (paramType instanceof Class<?>) { // We finally got a straight Class... return (Class<?>) paramType; } return null; } /** * Extract the generic type from the given Class<?> object. * * @param clazz the Class<?> to check * @param source the expected raw source type (can be <code>null</code>) * @param typeIndex the index of the actual type argument * @return the generic type as Class, or <code>null</code> if none */ private static Class<?> extractTypeFromClass(Class<?> clazz, Class<?> source, int typeIndex) { return extractTypeFromClass(null, clazz, source, typeIndex, 1, 1); } /** * Extract the generic type from the given Class<?> object. * * @param methodParam the method parameter specification * @param clazz the Class<?> to check * @param source the expected raw source type (can be <code>null</code>) * @param typeIndex the index of the actual type argument * @param nestingLevel the nesting level of the target type * @param currentLevel the current nested level * @return the generic type as Class, or <code>null</code> if none */ private static Class<?> extractTypeFromClass( MethodParameter methodParam, Class<?> clazz, Class<?> source, int typeIndex, int nestingLevel, int currentLevel) { if (clazz.getName().startsWith("java.util.")) { return nu