Skip to content

Commit a4803d8

Browse files
committed
Convenient forType methods for ParameterizedTypeReference
Issue: SPR-16054 (cherry picked from commit 53091c7)
1 parent ab081c4 commit a4803d8

File tree

4 files changed

+74
-13
lines changed

4 files changed

+74
-13
lines changed

spring-core/src/main/java/org/springframework/core/ParameterizedTypeReference.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ protected ParameterizedTypeReference() {
5353
this.type = parameterizedType.getActualTypeArguments()[0];
5454
}
5555

56+
private ParameterizedTypeReference(Type type) {
57+
this.type = type;
58+
}
59+
5660

5761
public Type getType() {
5862
return this.type;
@@ -75,6 +79,19 @@ public String toString() {
7579
}
7680

7781

82+
/**
83+
* Build a {@code ParameterizedTypeReference} wrapping the given type.
84+
* @param type a generic type (possibly obtained via reflection,
85+
* e.g. from {@link java.lang.reflect.Method#getGenericReturnType()})
86+
* @return a corresponding reference which may be passed into
87+
* {@code ParameterizedTypeReference}-accepting methods
88+
* @since 4.3.12
89+
*/
90+
public static <T> ParameterizedTypeReference<T> forType(Type type) {
91+
return new ParameterizedTypeReference<T>(type) {
92+
};
93+
}
94+
7895
private static Class<?> findParameterizedTypeReferenceSubclass(Class<?> child) {
7996
Class<?> parent = child.getSuperclass();
8097
if (Object.class == parent) {

spring-core/src/main/java/org/springframework/core/ResolvableType.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,19 @@ public static ResolvableType forType(Type type, ResolvableType owner) {
13091309
return forType(type, variableResolver);
13101310
}
13111311

1312+
1313+
/**
1314+
* Return a {@link ResolvableType} for the specified {@link ParameterizedTypeReference}.
1315+
* Note: The resulting {@link ResolvableType} may not be {@link Serializable}.
1316+
* @param typeReference the reference to obtain the source type from
1317+
* @return a {@link ResolvableType} for the specified {@link ParameterizedTypeReference}
1318+
* @since 4.3.12
1319+
* @see #forType(Type)
1320+
*/
1321+
public static ResolvableType forType(ParameterizedTypeReference<?> typeReference) {
1322+
return forType(typeReference.getType(), null, null);
1323+
}
1324+
13121325
/**
13131326
* Return a {@link ResolvableType} for the specified {@link Type} backed by a given
13141327
* {@link VariableResolver}.
@@ -1545,7 +1558,7 @@ public static WildcardBounds get(ResolvableType type) {
15451558
}
15461559
WildcardType wildcardType = (WildcardType) resolveToWildcard.type;
15471560
Kind boundsType = (wildcardType.getLowerBounds().length > 0 ? Kind.LOWER : Kind.UPPER);
1548-
Type[] bounds = boundsType == Kind.UPPER ? wildcardType.getUpperBounds() : wildcardType.getLowerBounds();
1561+
Type[] bounds = (boundsType == Kind.UPPER ? wildcardType.getUpperBounds() : wildcardType.getLowerBounds());
15491562
ResolvableType[] resolvableBounds = new ResolvableType[bounds.length];
15501563
for (int i = 0; i < bounds.length; i++) {
15511564
resolvableBounds[i] = ResolvableType.forType(bounds[i], type.variableResolver);

spring-core/src/test/java/org/springframework/core/ParameterizedTypeReferenceTests.java

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,25 +33,40 @@
3333
public class ParameterizedTypeReferenceTests {
3434

3535
@Test
36-
public void map() throws NoSuchMethodException {
36+
public void stringTypeReference() {
37+
ParameterizedTypeReference<String> typeReference = new ParameterizedTypeReference<String>() {};
38+
assertEquals(String.class, typeReference.getType());
39+
}
40+
41+
@Test
42+
public void mapTypeReference() throws Exception {
3743
Type mapType = getClass().getMethod("mapMethod").getGenericReturnType();
38-
ParameterizedTypeReference<Map<Object,String>> mapTypeReference = new ParameterizedTypeReference<Map<Object,String>>() {};
39-
assertEquals(mapType, mapTypeReference.getType());
44+
ParameterizedTypeReference<Map<Object,String>> typeReference = new ParameterizedTypeReference<Map<Object,String>>() {};
45+
assertEquals(mapType, typeReference.getType());
4046
}
4147

4248
@Test
43-
public void list() throws NoSuchMethodException {
44-
Type mapType = getClass().getMethod("listMethod").getGenericReturnType();
45-
ParameterizedTypeReference<List<String>> mapTypeReference = new ParameterizedTypeReference<List<String>>() {};
46-
assertEquals(mapType, mapTypeReference.getType());
49+
public void listTypeReference() throws Exception {
50+
Type listType = getClass().getMethod("listMethod").getGenericReturnType();
51+
ParameterizedTypeReference<List<String>> typeReference = new ParameterizedTypeReference<List<String>>() {};
52+
assertEquals(listType, typeReference.getType());
4753
}
4854

4955
@Test
50-
public void string() {
51-
ParameterizedTypeReference<String> typeReference = new ParameterizedTypeReference<String>() {};
52-
assertEquals(String.class, typeReference.getType());
56+
public void reflectiveTypeReferenceWithSpecificDeclaration() throws Exception{
57+
Type listType = getClass().getMethod("listMethod").getGenericReturnType();
58+
ParameterizedTypeReference<List<String>> typeReference = ParameterizedTypeReference.forType(listType);
59+
assertEquals(listType, typeReference.getType());
5360
}
5461

62+
@Test
63+
public void reflectiveTypeReferenceWithGenericDeclaration() throws Exception{
64+
Type listType = getClass().getMethod("listMethod").getGenericReturnType();
65+
ParameterizedTypeReference<?> typeReference = ParameterizedTypeReference.forType(listType);
66+
assertEquals(listType, typeReference.getType());
67+
}
68+
69+
5570
public static Map<Object, String> mapMethod() {
5671
return null;
5772
}

spring-core/src/test/java/org/springframework/core/ResolvableTypeTests.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2017 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -869,6 +869,22 @@ public void resolveTypeWithCustomVariableResolver() throws Exception {
869869
assertThat(this.typeVariableCaptor.getValue().getName(), equalTo("T"));
870870
}
871871

872+
@Test
873+
public void resolveTypeVariableFromReflectiveParameterizedTypeReference() throws Exception {
874+
Type sourceType = Methods.class.getMethod("typedReturn").getGenericReturnType();
875+
ResolvableType type = ResolvableType.forType(ParameterizedTypeReference.forType(sourceType));
876+
assertThat(type.resolve(), nullValue());
877+
assertThat(type.getType().toString(), equalTo("T"));
878+
}
879+
880+
@Test
881+
public void resolveTypeVariableFromDeclaredParameterizedTypeReference() throws Exception {
882+
Type sourceType = Methods.class.getMethod("charSequenceReturn").getGenericReturnType();
883+
ResolvableType reflectiveType = ResolvableType.forType(sourceType);
884+
ResolvableType declaredType = ResolvableType.forType(new ParameterizedTypeReference<List<CharSequence>>() {});
885+
assertEquals(reflectiveType, declaredType);
886+
}
887+
872888
@Test
873889
public void toStrings() throws Exception {
874890
assertThat(ResolvableType.NONE.toString(), equalTo("?"));

0 commit comments

Comments
 (0)