Origin

The type conversion in Hutool originally started as a utility class called “Convert”, with a static method for each type conversion. However, this approach had a potential problem with extensibility, which meant that Hutool could only meet the needs of some type conversions.

Solution

To address these issues, I made extensions to the class in Hutool. The idea is as follows:

  • Converter is an interface for type conversion, which is implemented by overriding the convert method to achieve conversion of different types of objects.
  • ConverterRegistry is a central registry for type conversions that stores various converter objects for converting between different types of objects. It uses the convert method to find the converter corresponding to the target type and convert the object to be converted. In this class, there are default converters and custom converters, where the default converters are some pre-defined converters in Hutool and the custom converters store user-defined converters.

This approach enables flexible type conversion for classes. Here is how to use it:

int a = 3423;
ConverterRegistry converterRegistry = ConverterRegistry.getInstance();
String result = converterRegistry.convert(String.class, a);
Assert.assertEquals("3423", result);

Custom Conversions

Sometimes the default conversions provided by Hutool cannot meet our needs for custom objects. In this case, we can use the ConverterRegistry.getInstance().putCustom() method to customize type conversions.

  1. Custom Converter
public static class CustomConverter implements Converter<String> {
    @Override
    public String convert(Object value, String defaultValue) throws IllegalArgumentException {
        return "Custom: " + value.toString();
    }
}
  1. Registering the Converter
ConverterRegistry converterRegistry = ConverterRegistry.getInstance();
// Here we demonstrate how to customize the String conversion, but please avoid replacing it if Hutool already provides a String converter (it could cause related conversion exceptions by affecting the global scope)
// converterRegistry.putCustom(String.class, CustomConverter.class);
  1. Executing the Conversion
int a = 454553;
String result = converterRegistry.convert(String.class, a);
Assert.assertEquals("Custom: 454553", result);

Note: The convert(Class<T> type, Object value, T defaultValue, boolean isCustomFirst) method has a last parameter that allows you to choose whether to prioritize using custom converters or default converters when converting. The convert(Class<T> type, Object value, T defaultValue) and convert(Class<T> type, Object value) overloaded methods both prioritize using custom converters.

Singleton and Object-based Usage of ConverterRegistry

ConverterRegistry provides a static method getInstance() to return a globally singleton object, which is the recommended usage method. However, if you want to customize conversions within a limited scope, you can instantiate a ConverterRegistry object.