Use flexible generic type level nullability in Converter

Allow defining converters that return non-null values by
leveraging flexible generic type level nullability in
org.springframework.core.convert.converter.Converter.

Closes gh-35947
This commit is contained in:
Sébastien Deleuze
2025-12-05 07:28:52 +01:00
parent 8b6d7e0da7
commit d36475cb4c
10 changed files with 14 additions and 13 deletions
@@ -29,12 +29,13 @@ import org.springframework.util.Assert;
*
* @author Keith Donald
* @author Josh Cummings
* @author Sebastien Deleuze
* @since 3.0
* @param <S> the source type
* @param <T> the target type
* @param <T> the target type (potentially {@code null})
*/
@FunctionalInterface
public interface Converter<S, T> {
public interface Converter<S, T extends @Nullable Object> {
/**
* Convert the source object of type {@code S} to target type {@code T}.
@@ -42,7 +43,7 @@ public interface Converter<S, T> {
* @return the converted object, which must be an instance of {@code T} (potentially {@code null})
* @throws IllegalArgumentException if the source cannot be converted to the desired target type
*/
@Nullable T convert(S source);
T convert(S source);
/**
* Construct a composed {@link Converter} that first applies this {@link Converter}
@@ -56,7 +57,7 @@ public interface Converter<S, T> {
* and then applies the {@code after} {@link Converter}
* @since 5.3
*/
default <U> Converter<S, U> andThen(Converter<? super T, ? extends U> after) {
default <U> Converter<S, @Nullable U> andThen(Converter<? super T, ? extends @Nullable U> after) {
Assert.notNull(after, "'after' Converter must not be null");
return (S s) -> {
T initialResult = convert(s);
@@ -107,7 +107,7 @@ public class ConvertingComparator<S, T> implements Comparator<S> {
/**
* Adapts a {@link ConversionService} and {@code targetType} to a {@link Converter}.
*/
private static class ConversionServiceConverter<S, T> implements Converter<S, T> {
private static class ConversionServiceConverter<S, T> implements Converter<S, @Nullable T> {
private final ConversionService conversionService;
@@ -31,7 +31,7 @@ import org.springframework.core.convert.converter.Converter;
* @author Sam Brannen
* @since 3.0
*/
final class StringToBooleanConverter implements Converter<String, Boolean> {
final class StringToBooleanConverter implements Converter<String, @Nullable Boolean> {
private static final Set<String> trueValues = Set.of("true", "on", "yes", "1");
@@ -26,7 +26,7 @@ import org.springframework.core.convert.converter.Converter;
* @author Keith Donald
* @since 3.0
*/
final class StringToCharacterConverter implements Converter<String, Character> {
final class StringToCharacterConverter implements Converter<String, @Nullable Character> {
@Override
public @Nullable Character convert(String source) {
@@ -37,7 +37,7 @@ final class StringToEnumConverterFactory implements ConverterFactory<String, Enu
}
private static class StringToEnum<T extends Enum> implements Converter<String, T> {
private static class StringToEnum<T extends Enum> implements Converter<String, @Nullable T> {
private final Class<T> enumType;
@@ -34,7 +34,7 @@ import org.springframework.util.StringUtils;
* @since 3.0
* @see StringUtils#parseLocale
*/
final class StringToLocaleConverter implements Converter<String, Locale> {
final class StringToLocaleConverter implements Converter<String, @Nullable Locale> {
@Override
public @Nullable Locale convert(String source) {
@@ -48,7 +48,7 @@ final class StringToNumberConverterFactory implements ConverterFactory<String, N
}
private static final class StringToNumber<T extends Number> implements Converter<String, T> {
private static final class StringToNumber<T extends Number> implements Converter<String, @Nullable T> {
private final Class<T> targetType;
@@ -29,7 +29,7 @@ import org.springframework.core.convert.converter.Converter;
* @author Stephane Nicoll
* @since 6.1
*/
final class StringToPatternConverter implements Converter<String, Pattern> {
final class StringToPatternConverter implements Converter<String, @Nullable Pattern> {
@Override
public @Nullable Pattern convert(String source) {
@@ -28,7 +28,7 @@ import org.springframework.core.convert.converter.Converter;
* @author Sebastien Deleuze
* @since 6.1
*/
final class StringToRegexConverter implements Converter<String, Regex> {
final class StringToRegexConverter implements Converter<String, @Nullable Regex> {
@Override
public @Nullable Regex convert(String source) {
@@ -30,7 +30,7 @@ import org.springframework.util.StringUtils;
* @since 3.2
* @see UUID#fromString
*/
final class StringToUUIDConverter implements Converter<String, UUID> {
final class StringToUUIDConverter implements Converter<String, @Nullable UUID> {
@Override
public @Nullable UUID convert(String source) {