diff --git a/spring-core/src/main/java/org/springframework/core/ResolvableType.java b/spring-core/src/main/java/org/springframework/core/ResolvableType.java index 80e9174d4c..7ec5f032d9 100644 --- a/spring-core/src/main/java/org/springframework/core/ResolvableType.java +++ b/spring-core/src/main/java/org/springframework/core/ResolvableType.java @@ -575,7 +575,8 @@ public final class ResolvableType implements Serializable { return (Class) this.type; } if (this.type instanceof GenericArrayType) { - return Array.newInstance(getComponentType().resolve(), 0).getClass(); + Class resolvedComponent = getComponentType().resolve(); + return (resolvedComponent == null ? null : Array.newInstance(resolvedComponent, 0).getClass()); } return resolveType().resolve(); } diff --git a/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java b/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java index f0d728eb82..b6b42006fb 100644 --- a/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java +++ b/spring-core/src/test/java/org/springframework/core/GenericTypeResolverTests.java @@ -144,6 +144,24 @@ public class GenericTypeResolverTests { assertThat(resolved, equalTo(new Class[] { Object.class })); } + @Test + public void getGenericsOnArrayFromParamCannotBeResolved() throws Exception { + // SPR-11044 + MethodParameter methodParameter = MethodParameter.forMethodOrConstructor( + WithArrayBase.class.getDeclaredMethod("array", Object[].class), 0); + Class resolved = GenericTypeResolver.resolveParameterType(methodParameter, WithArray.class); + assertThat(resolved, equalTo((Class) Object[].class)); + } + + @Test + public void getGenericsOnArrayFromReturnCannotBeResolved() throws Exception { + // SPR-11044 + Class resolved = GenericTypeResolver.resolveReturnType( + WithArrayBase.class.getDeclaredMethod("array", Object[].class), + WithArray.class); + assertThat(resolved, equalTo((Class) Object[].class)); + } + public interface MyInterfaceType { } @@ -279,4 +297,14 @@ public class GenericTypeResolverTests { } } + static abstract class WithArrayBase { + + public abstract T[] array(T... args); + + } + + static abstract class WithArray extends WithArrayBase { + + } + } diff --git a/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java b/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java index 24db8da68d..04e727d804 100644 --- a/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java +++ b/spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java @@ -519,6 +519,30 @@ public class ResolvableTypeTests { assertThat(generic.resolve(), equalTo((Class) String[].class)); } + @Test + public void resolveVariableGenericArray() throws Exception { + ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray"), TypedFields.class); + assertThat(type.getType().toString(), equalTo("T[]")); + assertThat(type.isArray(), equalTo(true)); + assertThat(type.resolve(), equalTo((Class) String[].class)); + } + + @Test + public void resolveVariableGenericArrayUnknown() throws Exception { + ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray")); + assertThat(type.getType().toString(), equalTo("T[]")); + assertThat(type.isArray(), equalTo(true)); + assertThat(type.resolve(), nullValue()); + } + + @Test + public void resolveVariableGenericArrayUnknownWithFallback() throws Exception { + ResolvableType type = ResolvableType.forField(Fields.class.getField("variableTypeGenericArray")); + assertThat(type.getType().toString(), equalTo("T[]")); + assertThat(type.isArray(), equalTo(true)); + assertThat(type.resolve(Object.class), equalTo((Class) Object.class)); + } + @Test public void resolveWildcardTypeUpperBounds() throws Exception { ResolvableType type = ResolvableType.forField(Fields.class.getField("wildcardType")); @@ -1253,6 +1277,8 @@ public class ResolvableTypeTests { public Map, Map> nested; + public T[] variableTypeGenericArray; + }