@Nullable public static Type resolveVariable( TypeVariable variable, final Class classType, boolean resolveInInterfacesOnly) { final Class aClass = getRawType(classType); int index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(aClass), variable); if (index >= 0) { return variable; } final Class[] classes = ReflectionCache.getInterfaces(aClass); final Type[] genericInterfaces = ReflectionCache.getGenericInterfaces(aClass); for (int i = 0; i <= classes.length; i++) { Class anInterface; if (i < classes.length) { anInterface = classes[i]; } else { anInterface = ReflectionCache.getSuperClass(aClass); if (resolveInInterfacesOnly || anInterface == null) { continue; } } final Type resolved = resolveVariable(variable, anInterface); if (resolved instanceof Class || resolved instanceof ParameterizedType) { return resolved; } if (resolved instanceof TypeVariable) { final TypeVariable typeVariable = (TypeVariable) resolved; index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(anInterface), typeVariable); if (index < 0) { LOG.error( "Cannot resolve type variable:\n" + "typeVariable = " + typeVariable + "\n" + "genericDeclaration = " + declarationToString(typeVariable.getGenericDeclaration()) + "\n" + "searching in " + declarationToString(anInterface)); } final Type type = i < genericInterfaces.length ? genericInterfaces[i] : aClass.getGenericSuperclass(); if (type instanceof Class) { return Object.class; } if (type instanceof ParameterizedType) { return getActualTypeArguments((ParameterizedType) type)[index]; } throw new AssertionError("Invalid type: " + type); } } return null; }
@Nullable public static Class<?> substituteGenericType(final Type genericType, final Type classType) { if (genericType instanceof TypeVariable) { final Class<?> aClass = getRawType(classType); final Type type = resolveVariable((TypeVariable) genericType, aClass); if (type instanceof Class) { return (Class) type; } if (type instanceof ParameterizedType) { return (Class<?>) ((ParameterizedType) type).getRawType(); } if (type instanceof TypeVariable && classType instanceof ParameterizedType) { final int index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(aClass), type); if (index >= 0) { return getRawType(getActualTypeArguments((ParameterizedType) classType)[index]); } } } else { return getRawType(genericType); } return null; }