/** * Return a {@link ResolvableType} for the specified {@link Type}. * <p>Note: The resulting {@link ResolvableType} instance may not be {@link Serializable}. * @param type the source type (potentially {@code null}) * @return a {@link ResolvableType} for the specified {@link Type} * @see #forType(Type, ResolvableType) */ public static ResolvableType forType(@Nullable Type type) { return forType(type, null, null); }
@Override @Nullable public ResolvableType resolveVariable(TypeVariable<?> variable) { Type type = this.typeVariableMap.get(variable); return (type != null ? ResolvableType.forType(type) : null); }
/** * Return a {@link ResolvableType} for the specified {@link Type} backed by a given * {@link VariableResolver}. * @param type the source type or {@code null} * @param variableResolver the variable resolver or {@code null} * @return a {@link ResolvableType} for the specified {@link Type} and {@link VariableResolver} */ static ResolvableType forType(@Nullable Type type, @Nullable VariableResolver variableResolver) { return forType(type, null, variableResolver); }
/** * Return a {@link ResolvableType} for the specified {@link Field}. * @param field the source field * @return a {@link ResolvableType} for the specified field * @see #forField(Field, Class) */ public static ResolvableType forField(Field field) { Assert.notNull(field, "Field must not be null"); return forType(null, new FieldTypeProvider(field), null); }
/** * Return a {@link ResolvableType} for the specified {@link ParameterizedTypeReference}. * <p>Note: The resulting {@link ResolvableType} instance may not be {@link Serializable}. * @param typeReference the reference to obtain the source type from * @return a {@link ResolvableType} for the specified {@link ParameterizedTypeReference} * @since 4.3.12 * @see #forType(Type) */ public static ResolvableType forType(ParameterizedTypeReference<?> typeReference) { return forType(typeReference.getType(), null, null); }
public AsyncResultMethodParameter(@Nullable Object returnValue) { super(-1); this.returnValue = returnValue; this.returnType = ResolvableType.forType(super.getGenericParameterType()).getGeneric(); }
/** * Variant of {@link #toMono(Class)} for type information with generics. * @param typeRef the type reference for the type to decode to * @param <T> the element type to decode to * @return {@code BodyExtractor} for {@code Mono<T>} */ public static <T> BodyExtractor<Mono<T>, ReactiveHttpInputMessage> toMono(ParameterizedTypeReference<T> typeRef) { return toMono(ResolvableType.forType(typeRef.getType())); }
/** * Variant of {@link #toFlux(Class)} for type information with generics. * @param typeRef the type reference for the type to decode to * @param <T> the element type to decode to * @return {@code BodyExtractor} for {@code Flux<T>} */ public static <T> BodyExtractor<Flux<T>, ReactiveHttpInputMessage> toFlux(ParameterizedTypeReference<T> typeRef) { return toFlux(ResolvableType.forType(typeRef.getType())); }
/** * Return the generic type of the {@code returnType} (or of the nested type * if it is an {@link HttpEntity}). */ private Type getGenericType(MethodParameter returnType) { if (HttpEntity.class.isAssignableFrom(returnType.getParameterType())) { return ResolvableType.forType(returnType.getGenericParameterType()).getGeneric().getType(); } else { return returnType.getGenericParameterType(); } }
/** * Resolve the top-level parameter type of the given {@code MethodParameter}. * @param methodParameter the method parameter to resolve * @since 4.1.9 * @see MethodParameter#setParameterType */ static void resolveMethodParameter(MethodParameter methodParameter) { Assert.notNull(methodParameter, "MethodParameter must not be null"); ResolvableType owner = forType(methodParameter.getContainingClass()).as(methodParameter.getDeclaringClass()); methodParameter.setParameterType( forType(null, new MethodParameterTypeProvider(methodParameter), owner.asVariableResolver()).resolve()); }
@Test public void resolveTypeVariableFromDeclaredParameterizedTypeReference() throws Exception { Type sourceType = Methods.class.getMethod("charSequenceReturn").getGenericReturnType(); ResolvableType reflectiveType = ResolvableType.forType(sourceType); ResolvableType declaredType = ResolvableType.forType(new ParameterizedTypeReference<List<CharSequence>>() {}); assertEquals(reflectiveType, declaredType); }
@Test public void resolveTypeVariableFromType() throws Exception { Type sourceType = Methods.class.getMethod("typedReturn").getGenericReturnType(); ResolvableType type = ResolvableType.forType(sourceType); assertThat(type.resolve(), nullValue()); assertThat(type.getType().toString(), equalTo("T")); }
@Test // Demonstrates we cant inject that event because the listener has a raw type public void genericListenerRawTypeTypeErasure() { GenericTestEvent<String> stringEvent = createGenericTestEvent("test"); ResolvableType eventType = ResolvableType.forType(stringEvent.getClass()); supportsEventType(true, RawApplicationListener.class, eventType); }
@Test // Demonstrates it works if we actually use the subtype public void genericListenerStrictTypeEventSubType() { StringEvent stringEvent = new StringEvent(this, "test"); ResolvableType eventType = ResolvableType.forType(stringEvent.getClass()); supportsEventType(true, StringEventListener.class, eventType); }
@Test public void genericListenerStrictTypeEventSubTypeNotMatching() { LongEvent stringEvent = new LongEvent(this, 123L); ResolvableType eventType = ResolvableType.forType(stringEvent.getClass()); supportsEventType(false, StringEventListener.class, eventType); }
@Test // Demonstrates we cant inject that event because the listener has a wildcard public void genericListenerWildcardTypeTypeErasure() { GenericTestEvent<String> stringEvent = createGenericTestEvent("test"); ResolvableType eventType = ResolvableType.forType(stringEvent.getClass()); supportsEventType(true, GenericEventListener.class, eventType); }
@Test public void resolveTypeVariableFromReflectiveParameterizedTypeReference() throws Exception { Type sourceType = Methods.class.getMethod("typedReturn").getGenericReturnType(); ResolvableType type = ResolvableType.forType(ParameterizedTypeReference.forType(sourceType)); assertThat(type.resolve(), nullValue()); assertThat(type.getType().toString(), equalTo("T")); }
@Test public void resolveTypeVariableFromTypeWithVariableResolver() throws Exception { Type sourceType = Methods.class.getMethod("typedReturn").getGenericReturnType(); ResolvableType type = ResolvableType.forType( sourceType, ResolvableType.forClass(TypedMethods.class).as(Methods.class).asVariableResolver()); assertThat(type.resolve(), equalTo((Class) String.class)); assertThat(type.getType().toString(), equalTo("T")); }
@Test public void narrow() throws Exception { ResolvableType type = ResolvableType.forField(Fields.class.getField("stringList")); ResolvableType narrow = ResolvableType.forType(ArrayList.class, type); assertThat(narrow.getGeneric().resolve(), equalTo(String.class)); }
@Test // gh-22042 public void decodeWithNullLiteral() { Flux<Object> result = this.decoder.decode(Flux.concat(stringBuffer("null")), ResolvableType.forType(Pojo.class), MediaType.APPLICATION_JSON, Collections.emptyMap()); StepVerifier.create(result).expectComplete().verify(); }