Skip to content

Instantly share code, notes, and snippets.

@winteryoung
Last active February 22, 2016 12:54
Show Gist options
  • Save winteryoung/e5947f13967e2f3166e7 to your computer and use it in GitHub Desktop.
Save winteryoung/e5947f13967e2f3166e7 to your computer and use it in GitHub Desktop.
java 泛型类型推导
// 输出 Integer
// 用法: GenericActualArgumentResolver.resolve(A.class, C.class, 0);
import com.google.common.collect.Lists;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
* 泛型参数实参类型解析器。
* 示例:
* <pre>
class A[T] extends B[T, Integer] { }
GenericActualArgumentResolver.resolve(A.class, B.class, 1); ==> 输出 java.lang.Integer
* </pre>
*
* @author fanshen
* @since 14-2-12
*/
public class GenericActualArgumentResolver {
private GenericActualArgumentResolver() { }
/**
* 泛型参数信息模型。
*/
private static class ParamTypeInfo {
/**
* 当前类上声明的泛型类型。
*/
private List<String> declaredTypes;
/**
* 向当前类的父类上应用的泛型类型。
*/
private List<String> appliedTypes;
private ParamTypeInfo(List<String> declaredTypes, List<String> appliedTypes) {
this.declaredTypes = declaredTypes;
this.appliedTypes = appliedTypes;
}
}
private static String resolveSuperGenericTypeParam(@Nullable Class klass,
@Nonnull Class superTypeThatDeclaresFormalTypeParam,
int typeParamIndex,
@Nonnull List<ParamTypeInfo> paramTypeInfoList) {
if (klass == null) {
return null;
}
Collection<ParameterizedType> genericSuperTypes = getGenericSuperTypes(klass);
addParamInfo(paramTypeInfoList, klass, genericSuperTypes);
for (ParameterizedType genericSuperType : genericSuperTypes) {
Class rawType = (Class) genericSuperType.getRawType();
if (rawType == superTypeThatDeclaresFormalTypeParam) {
return deductParam(paramTypeInfoList, typeParamIndex);
}
}
return resolveSuperGenericTypeParam(klass.getSuperclass(),
superTypeThatDeclaresFormalTypeParam,
typeParamIndex,
paramTypeInfoList);
}
private static void addParamInfo(List<ParamTypeInfo> paramTypeInfoList,
Class klass,
Collection<ParameterizedType> genericSuperTypes) {
List<String> declaredTypes = calcDeclaredTypes(klass);
List<String> appliedTypes = calcAppliedTypes(genericSuperTypes);
ParamTypeInfo paramTypeInfo = new ParamTypeInfo(declaredTypes, appliedTypes);
paramTypeInfoList.add(paramTypeInfo);
}
private static List<String> calcAppliedTypes(Collection<ParameterizedType> genericSuperTypes) {
List<String> appliedTypes = Lists.newArrayList();
for (ParameterizedType genericSuperType : genericSuperTypes) {
Type[] actualTypeArguments = genericSuperType.getActualTypeArguments();
String fqName;
for (Type actualTypeArgument : actualTypeArguments) {
if ((actualTypeArgument instanceof TypeVariable)) {
TypeVariable typeVariable = (TypeVariable) actualTypeArgument;
fqName = typeVariable.getName();
} else if (actualTypeArgument instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) actualTypeArgument;
Class rawType = (Class) parameterizedType.getRawType();
fqName = rawType.getName();
} else if (actualTypeArgument instanceof Class) {
Class typeArgClass = (Class) actualTypeArgument;
fqName = typeArgClass.getName();
} else {
fqName = "";
}
if (fqName == null) {
fqName = "";
}
int index = fqName.indexOf(" ");
if (index < 0) {
index = fqName.indexOf("\t");
}
if (index > 0) {
fqName = fqName.substring(0, index);
}
appliedTypes.add(fqName);
}
}
return appliedTypes;
}
private static List<String> calcDeclaredTypes(Class klass) {
List<String> declaredTypes = Lists.newArrayList();
{
TypeVariable[] typeParameters = klass.getTypeParameters();
for (TypeVariable typeParameter : typeParameters) {
String fqName = typeParameter.getName();
if (fqName == null) {
fqName = "";
}
int index = fqName.indexOf(" ");
if (index < 0) {
index = fqName.indexOf("\t");
}
if (index > 0) {
fqName = fqName.substring(0, index);
}
declaredTypes.add(fqName);
}
}
return declaredTypes;
}
private static Collection<ParameterizedType> getGenericSuperTypes(Class klass) {
List<Type> superTypes = Lists.newArrayList();
List<ParameterizedType> genericSuperTypes = Lists.newArrayList();
Type genericSuperclass = klass.getGenericSuperclass();
if (genericSuperclass != null) {
superTypes.add(genericSuperclass);
}
Type[] genericInterfaces = klass.getGenericInterfaces();
if (genericInterfaces != null) {
Collections.addAll(superTypes, genericInterfaces);
}
for (Type superType : superTypes) {
if (!(superType instanceof ParameterizedType)) {
continue;
}
ParameterizedType parameterizedType = (ParameterizedType) superType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
if (actualTypeArguments == null || actualTypeArguments.length <= 0) {
continue;
}
genericSuperTypes.add(parameterizedType);
}
return genericSuperTypes;
}
private static String deductParam(List<ParamTypeInfo> paramTypeInfoList, int typeParamIndex) {
if (paramTypeInfoList.size() <= 0) {
return null;
}
String targetType = null;
int declaredTypeIndex = -1;
for (int i = paramTypeInfoList.size() - 1; i >= 0; i--) {
ParamTypeInfo paramTypeInfo = paramTypeInfoList.get(i);
List<String> declaredTypes = paramTypeInfo.declaredTypes;
List<String> appliedTypes = paramTypeInfo.appliedTypes;
if (declaredTypeIndex < 0) {
targetType = appliedTypes.get(typeParamIndex);
} else {
targetType = appliedTypes.get(declaredTypeIndex);
}
boolean found = false;
for (int j = 0; j < declaredTypes.size(); j++) {
String declaredType = declaredTypes.get(j);
if (declaredType.equals(targetType)) {
declaredTypeIndex = j;
found = true;
break;
}
}
// 没有找到声明的参数说明应用的参数不是泛型变量,可以直接给出结果
if (!found) {
return targetType;
}
}
if (targetType == null) {
return null;
}
return targetType;
}
/**
* 解析。
*
* @param klass 含有泛型实参信息的类型
* @param superTypeThatDeclaresFormalTypeParam 含有泛型形参信息的基类类型
* @param typeParamIndex 泛型参数在 superTypeThatDeclaresFormalTypeParam 中的索引(0起)
*/
public static String resolve(@Nonnull Class klass,
@Nonnull Class superTypeThatDeclaresFormalTypeParam,
int typeParamIndex) {
return resolveSuperGenericTypeParam(klass,
superTypeThatDeclaresFormalTypeParam,
typeParamIndex,
Lists.<ParamTypeInfo>newArrayList());
}
/**
* 解析。
*
* @param klass 含有泛型实参信息的类型
* @param superTypeThatDeclaresFormalTypeParam 含有泛型形参信息的基类类型
* @param typeParamIndex 泛型参数在 superTypeThatDeclaresFormalTypeParam 中的索引(0起)
*/
public static Class<?> resolveToClass(@Nonnull Class klass,
@Nonnull Class superTypeThatDeclaresFormalTypeParam,
int typeParamIndex) {
String typeName = resolve(klass, superTypeThatDeclaresFormalTypeParam, typeParamIndex);
if (typeName == null) {
return null;
}
Class<?> extensionClass;
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
try {
extensionClass = contextClassLoader.loadClass(typeName);
} catch (ClassNotFoundException e) {
throw new RuntimeException("无法加载类:" + typeName, e);
}
return extensionClass;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment