GenericTypeResolver returns null for entirely unresolvable type arguments only

Issue: SPR-11763
This commit is contained in:
Juergen Hoeller 2014-05-06 18:06:26 +02:00
parent db5d651057
commit bea34ea41c
3 changed files with 46 additions and 12 deletions

View File

@ -243,10 +243,10 @@ public abstract class GenericTypeResolver {
*/
public static Class<?>[] resolveTypeArguments(Class<?> clazz, Class<?> genericIfc) {
ResolvableType type = ResolvableType.forClass(clazz).as(genericIfc);
if (!type.hasGenerics() || type.hasUnresolvableGenerics()) {
if (!type.hasGenerics() || type.isEntirelyUnresolvable()) {
return null;
}
return type.resolveGenerics();
return type.resolveGenerics(Object.class);
}
/**

View File

@ -416,7 +416,24 @@ public final class ResolvableType implements Serializable {
}
/**
* Determine whether the underlying type has unresolvable generics:
* Return {@code true} if this type contains unresolvable generics only,
* that is, no substitute for any of its declared type variables.
*/
boolean isEntirelyUnresolvable() {
if (this == NONE) {
return false;
}
ResolvableType[] generics = getGenerics();
for (ResolvableType generic : generics) {
if (!generic.isUnresolvableTypeVariable() && !generic.isWildcardWithoutBounds()) {
return false;
}
}
return true;
}
/**
* Determine whether the underlying type has any unresolvable generics:
* either through an unresolvable type variable on the type itself
* or through implementing a generic interface in a raw fashion,
* i.e. without substituting that interface's type variables.
@ -634,8 +651,8 @@ public final class ResolvableType implements Serializable {
/**
* Convenience method that will {@link #getGeneric(int...) get} and
* {@link #resolve() resolve} a specific generic parameters.
* @param indexes the indexes that refer to the generic parameter (may be omitted to
* return the first generic)
* @param indexes the indexes that refer to the generic parameter
* (may be omitted to return the first generic)
* @return a resolved {@link Class} or {@code null}
* @see #getGeneric(int...)
* @see #resolve()
@ -645,11 +662,11 @@ public final class ResolvableType implements Serializable {
}
/**
* Resolve this type to a {@link java.lang.Class}, returning {@code null} if the type
* cannot be resolved. This method will consider bounds of {@link TypeVariable}s and
* {@link WildcardType}s if direct resolution fails; however, bounds of
* {@code Object.class} will be ignored.
* @return the resolved {@link Class} or {@code null}
* Resolve this type to a {@link java.lang.Class}, returning {@code null}
* if the type cannot be resolved. This method will consider bounds of
* {@link TypeVariable}s and {@link WildcardType}s if direct resolution fails;
* however, bounds of {@code Object.class} will be ignored.
* @return the resolved {@link Class}, or {@code null} if not resolvable
* @see #resolve(Class)
* @see #resolveGeneric(int...)
* @see #resolveGenerics()

View File

@ -16,6 +16,7 @@
package org.springframework.core;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
@ -166,11 +167,21 @@ public class GenericTypeResolverTests {
public void getGenericsOnArrayFromReturnCannotBeResolved() throws Exception {
// SPR-11044
Class<?> resolved = GenericTypeResolver.resolveReturnType(
WithArrayBase.class.getDeclaredMethod("array", Object[].class),
WithArray.class);
WithArrayBase.class.getDeclaredMethod("array", Object[].class), WithArray.class);
assertThat(resolved, equalTo((Class) Object[].class));
}
@Test
public void resolveIncompleteTypeVariables() {
// SPR-11763
Class<?>[] resolved = GenericTypeResolver.resolveTypeArguments(IdFixingRepository.class, Repository.class);
assertNotNull(resolved);
assertEquals(2, resolved.length);
assertEquals(Object.class, resolved[0]);
assertEquals(Long.class, resolved[1]);
}
public interface MyInterfaceType<T> {
}
@ -314,4 +325,10 @@ public class GenericTypeResolverTests {
static abstract class WithArray<T> extends WithArrayBase<T> {
}
interface Repository<T, ID extends Serializable> {
}
interface IdFixingRepository<T> extends Repository<T, Long> {
}
}