in src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java [1352:1427]
private static boolean isAssignable(final Type type, final WildcardType toWildcardType,
final Map<TypeVariable<?>, Type> typeVarAssigns) {
if (type == null) {
return true;
}
// only a null type can be assigned to null type which
// would have cause the previous to return true
if (toWildcardType == null) {
return false;
}
// all types are assignable to themselves
if (toWildcardType.equals(type)) {
return true;
}
final Type[] toUpperBounds = getImplicitUpperBounds(toWildcardType);
final Type[] toLowerBounds = getImplicitLowerBounds(toWildcardType);
if (type instanceof WildcardType) {
final WildcardType wildcardType = (WildcardType) type;
final Type[] upperBounds = getImplicitUpperBounds(wildcardType);
final Type[] lowerBounds = getImplicitLowerBounds(wildcardType);
for (Type toBound : toUpperBounds) {
// if there are assignments for unresolved type variables,
// now's the time to substitute them.
toBound = substituteTypeVariables(toBound, typeVarAssigns);
// each upper bound of the subject type has to be assignable to
// each
// upper bound of the target type
for (final Type bound : upperBounds) {
if (!isAssignable(bound, toBound, typeVarAssigns)) {
return false;
}
}
}
for (Type toBound : toLowerBounds) {
// if there are assignments for unresolved type variables,
// now's the time to substitute them.
toBound = substituteTypeVariables(toBound, typeVarAssigns);
// each lower bound of the target type has to be assignable to
// each
// lower bound of the subject type
for (final Type bound : lowerBounds) {
if (!isAssignable(toBound, bound, typeVarAssigns)) {
return false;
}
}
}
return true;
}
for (final Type toBound : toUpperBounds) {
// if there are assignments for unresolved type variables,
// now's the time to substitute them.
if (!isAssignable(type, substituteTypeVariables(toBound, typeVarAssigns),
typeVarAssigns)) {
return false;
}
}
for (final Type toBound : toLowerBounds) {
// if there are assignments for unresolved type variables,
// now's the time to substitute them.
if (!isAssignable(substituteTypeVariables(toBound, typeVarAssigns), type,
typeVarAssigns)) {
return false;
}
}
return true;
}