基於Mybatis-3.5.0版本java
爲何要單獨拿一篇文章來說呢?由於裏面涉及到的java-Type接口的內容以前沒有接觸和了解過。我相信在座的不少小夥伴也必定不知道其中的奧祕哦~
你知道Class對象還有一個父接口嗎?apache
如下內容均摘錄自 徐郡明 《Mybatis技術內幕》數組
先簡單介紹一下Type接口的基礎知識。Type是全部類型的父接口,它有四個子接口和一個實現類,以下圖: ide
下面來看這些子接口和子類所表明的類型工具
org.apache.ibatis.reflection.TypeParameterResolver
是一個主要用來負責解析字段類型、方法返回值類型和方法參數列表中各個參數的類型的一個工具類。代碼以下:單元測試
/** * 暴露了三個公用靜態方法,分別用於解析Field類型、Method返回類型、方法參數類型 * @author Iwao AVE! */
public class TypeParameterResolver {
/** * 解析屬性類型 * @return The field type as {@link Type}. If it has type parameters in the * declaration,<br> * they will be resolved to the actual runtime {@link Type}s. */
public static Type resolveFieldType(Field field, Type srcType) {
// 屬性類型
Type fieldType = field.getGenericType();
// 定義的類
Class<?> declaringClass = field.getDeclaringClass();
// 解析類型
return resolveType(fieldType, srcType, declaringClass);
}
/** * 解析方法返回值類型 * @return The return type of the method as {@link Type}. If it has type * parameters in the declaration,<br> * they will be resolved to the actual runtime {@link Type}s. */
public static Type resolveReturnType(Method method, Type srcType) {
// 返回值類型
Type returnType = method.getGenericReturnType();
// 定義的類
Class<?> declaringClass = method.getDeclaringClass();
// 解析類型
return resolveType(returnType, srcType, declaringClass);
}
/** * 解析方法參數類型 * @return The parameter types of the method as an array of {@link Type}s. If * they have type parameters in the declaration,<br> * they will be resolved to the actual runtime {@link Type}s. */
public static Type[] resolveParamTypes(Method method, Type srcType) {
// 參數類型
Type[] paramTypes = method.getGenericParameterTypes();
// 定義的類
Class<?> declaringClass = method.getDeclaringClass();
Type[] result = new Type[paramTypes.length];
for (int i = 0; i < paramTypes.length; i++) {
// 解析類型
result[i] = resolveType(paramTypes[i], srcType, declaringClass);
}
return result;
}
/** * 解析類型 * @param type 類型 * @param srcType 來源類型 * @param declaringClass 定義的類 * @return 解析後的類型 */
private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
if (type instanceof TypeVariable) {// 解析TypeVariable
return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
} else if (type instanceof ParameterizedType) {// 解析ParameterizedType
return resolveParameterizedType((ParameterizedType) type, srcType, declaringClass);
} else if (type instanceof GenericArrayType) {// 解析GenericArrayType
return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
} else {
return type;// Class類型直接返回
}
}
private static Type resolveGenericArrayType(GenericArrayType genericArrayType, Type srcType, Class<?> declaringClass) {
Type componentType = genericArrayType.getGenericComponentType();
Type resolvedComponentType = null;
if (componentType instanceof TypeVariable) {
resolvedComponentType = resolveTypeVar((TypeVariable<?>) componentType, srcType, declaringClass);
} else if (componentType instanceof GenericArrayType) {
resolvedComponentType = resolveGenericArrayType((GenericArrayType) componentType, srcType, declaringClass);
} else if (componentType instanceof ParameterizedType) {
resolvedComponentType = resolveParameterizedType((ParameterizedType) componentType, srcType,
declaringClass);
}
if (resolvedComponentType instanceof Class) {
return Array.newInstance((Class<?>) resolvedComponentType, 0).getClass();
} else {
return new GenericArrayTypeImpl(resolvedComponentType);
}
}
/** * 解析 ParameterizedType 類型 * @param parameterizedType ParameterizedType 類型 * @param srcType 來源類型 * @param declaringClass 定義的類 * @return 解析後的類型 */
private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Type srcType, Class<?> declaringClass) {
Class<?> rawType = (Class<?>) parameterizedType.getRawType();
// 解析 <> 中實際類型
Type[] typeArgs = parameterizedType.getActualTypeArguments();
Type[] args = new Type[typeArgs.length];
for (int i = 0; i < typeArgs.length; i++) {
if (typeArgs[i] instanceof TypeVariable) {
args[i] = resolveTypeVar((TypeVariable<?>) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof ParameterizedType) {
args[i] = resolveParameterizedType((ParameterizedType) typeArgs[i], srcType, declaringClass);
} else if (typeArgs[i] instanceof WildcardType) {
args[i] = resolveWildcardType((WildcardType) typeArgs[i], srcType, declaringClass);
} else {
args[i] = typeArgs[i];
}
}
return new ParameterizedTypeImpl(rawType, null, args);
}
private static Type resolveWildcardType(WildcardType wildcardType, Type srcType, Class<?> declaringClass) {
Type[] lowerBounds = resolveWildcardTypeBounds(wildcardType.getLowerBounds(), srcType, declaringClass);
Type[] upperBounds = resolveWildcardTypeBounds(wildcardType.getUpperBounds(), srcType, declaringClass);
return new WildcardTypeImpl(lowerBounds, upperBounds);
}
private static Type[] resolveWildcardTypeBounds(Type[] bounds, Type srcType, Class<?> declaringClass) {
Type[] result = new Type[bounds.length];
for (int i = 0; i < bounds.length; i++) {
if (bounds[i] instanceof TypeVariable) {
result[i] = resolveTypeVar((TypeVariable<?>) bounds[i], srcType, declaringClass);
} else if (bounds[i] instanceof ParameterizedType) {
result[i] = resolveParameterizedType((ParameterizedType) bounds[i], srcType, declaringClass);
} else if (bounds[i] instanceof WildcardType) {
result[i] = resolveWildcardType((WildcardType) bounds[i], srcType, declaringClass);
} else {
result[i] = bounds[i];
}
}
return result;
}
/** * 解析TypeVariable類型 * @param typeVar * @param srcType * @param declaringClass * @return */
private static Type resolveTypeVar(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass) {
Type result = null;
Class<?> clazz = null;
if (srcType instanceof Class) {
clazz = (Class<?>) srcType;
} else if (srcType instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) srcType;
clazz = (Class<?>) parameterizedType.getRawType();
} else {
throw new IllegalArgumentException(
"The 2nd arg must be Class or ParameterizedType, but was: " + srcType.getClass());
}
if (clazz == declaringClass) {
Type[] bounds = typeVar.getBounds();
if (bounds.length > 0) {
return bounds[0];
}
return Object.class;
}
Type superclass = clazz.getGenericSuperclass();
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superclass);
if (result != null) {
return result;
}
Type[] superInterfaces = clazz.getGenericInterfaces();
for (Type superInterface : superInterfaces) {
result = scanSuperTypes(typeVar, srcType, declaringClass, clazz, superInterface);
if (result != null) {
return result;
}
}
return Object.class;
}
private static Type scanSuperTypes(TypeVariable<?> typeVar, Type srcType, Class<?> declaringClass, Class<?> clazz, Type superclass) {
if (superclass instanceof ParameterizedType) {
ParameterizedType parentAsType = (ParameterizedType) superclass;
Class<?> parentAsClass = (Class<?>) parentAsType.getRawType();
TypeVariable<?>[] parentTypeVars = parentAsClass.getTypeParameters();
if (srcType instanceof ParameterizedType) {
parentAsType = translateParentTypeVars((ParameterizedType) srcType, clazz, parentAsType);
}
if (declaringClass == parentAsClass) {
for (int i = 0; i < parentTypeVars.length; i++) {
if (typeVar == parentTypeVars[i]) {
return parentAsType.getActualTypeArguments()[i];
}
}
}
if (declaringClass.isAssignableFrom(parentAsClass)) {
return resolveTypeVar(typeVar, parentAsType, declaringClass);
}
} else if (superclass instanceof Class && declaringClass.isAssignableFrom((Class<?>) superclass)) {
return resolveTypeVar(typeVar, superclass, declaringClass);
}
return null;
}
private static ParameterizedType translateParentTypeVars(ParameterizedType srcType, Class<?> srcClass, ParameterizedType parentType) {
Type[] parentTypeArgs = parentType.getActualTypeArguments();
Type[] srcTypeArgs = srcType.getActualTypeArguments();
TypeVariable<?>[] srcTypeVars = srcClass.getTypeParameters();
Type[] newParentArgs = new Type[parentTypeArgs.length];
boolean noChange = true;
for (int i = 0; i < parentTypeArgs.length; i++) {
if (parentTypeArgs[i] instanceof TypeVariable) {
for (int j = 0; j < srcTypeVars.length; j++) {
if (srcTypeVars[j] == parentTypeArgs[i]) {
noChange = false;
newParentArgs[i] = srcTypeArgs[j];
}
}
} else {
newParentArgs[i] = parentTypeArgs[i];
}
}
return noChange ? parentType
: new ParameterizedTypeImpl((Class<?>) parentType.getRawType(), null, newParentArgs);
}
private TypeParameterResolver() {
super();
}
static class ParameterizedTypeImpl implements ParameterizedType {
private Class<?> rawType;
private Type ownerType;
private Type[] actualTypeArguments;
public ParameterizedTypeImpl(Class<?> rawType, Type ownerType, Type[] actualTypeArguments) {
super();
this.rawType = rawType;
this.ownerType = ownerType;
this.actualTypeArguments = actualTypeArguments;
}
@Override
public Type[] getActualTypeArguments() {
return actualTypeArguments;
}
@Override
public Type getOwnerType() {
return ownerType;
}
@Override
public Type getRawType() {
return rawType;
}
@Override
public String toString() {
return "ParameterizedTypeImpl [rawType=" + rawType + ", ownerType=" + ownerType + ", actualTypeArguments="
+ Arrays.toString(actualTypeArguments) + "]";
}
}
static class WildcardTypeImpl implements WildcardType {
private Type[] lowerBounds;
private Type[] upperBounds;
WildcardTypeImpl(Type[] lowerBounds, Type[] upperBounds) {
super();
this.lowerBounds = lowerBounds;
this.upperBounds = upperBounds;
}
@Override
public Type[] getLowerBounds() {
return lowerBounds;
}
@Override
public Type[] getUpperBounds() {
return upperBounds;
}
}
static class GenericArrayTypeImpl implements GenericArrayType {
private Type genericComponentType;
GenericArrayTypeImpl(Type genericComponentType) {
super();
this.genericComponentType = genericComponentType;
}
@Override
public Type getGenericComponentType() {
return genericComponentType;
}
}
}
複製代碼
能夠經過調試org.apache.ibatis.reflection.TypeParameterResolverTest
這個單元測試類,觸發不一樣的場景去深刻了解Java-Type。 測試
失控的阿甘,樂於分享,記錄點滴this