自定义类型转换 - ConverterRegistry
 # 自定义类型转换 - ConverterRegistry
# 1. 由来
Hutool 中的类型转换最初是通过 Convert 工具类实现的,每种类型的转换都是通过静态方法来表示。然而,这种方式的扩展性较差,无法满足所有可能的类型转换需求。因此,Hutool 引入了 ConverterRegistry,用于管理类型转换器并提供更灵活的类型转换机制。
# 2. 解决方案
为了提升扩展性,Hutool 提供了以下解决方案:
Converter接口:这是一个类型转换接口。通过实现这个接口并重写其convert方法,可以自定义对象的类型转换逻辑。ConverterRegistry类型转换登记中心:这是一个管理所有类型转换器的中心。ConverterRegistry存储了 Hutool 中的默认转换器和用户自定义的转换器。通过ConverterRegistry的convert方法,可以自动查找目标类型的转换器,并将对象转换为指定类型。
# 2.1 示例代码
int a = 3423;
ConverterRegistry converterRegistry = ConverterRegistry.getInstance(); // 获取 ConverterRegistry 的单例实例
String result = converterRegistry.convert(String.class, a); // 将整数 a 转换为字符串
Assert.assertEquals("3423", result); // 断言结果为 "3423"
 2
3
4
API 使用说明
ConverterRegistry.getInstance():- 作用:返回 
ConverterRegistry的单例实例。此方法保证全局只有一个ConverterRegistry实例,所有类型转换都通过这个实例管理。 - 语法:
ConverterRegistry.getInstance() - 参数:无。
 - 返回值:返回 
ConverterRegistry的单例实例。 
- 作用:返回 
 convert(Class<T> type, Object value):- 作用:将 
value转换为指定的type类型。 - 语法:
<T> T convert(Class<T> type, Object value) - 参数:
type:目标类型的Class对象。例如,String.class。value:要转换的对象。
 - 返回值:转换后的对象,类型为 
T。 
- 作用:将 
 
# 2.2 实际开发中的应用
在实际开发中,ConverterRegistry 非常适合用于将一种类型的对象动态转换为另一种类型。例如,将数据库字段值转换为 Java 对象的属性值,或者在多层架构中进行对象跨层转换。
public class Application {
    public static void main(String[] args) {
        ConverterRegistry converterRegistry = ConverterRegistry.getInstance();
        // 将整数转换为字符串
        int userId = 12345;
        String userIdStr = converterRegistry.convert(String.class, userId);
        
        // 将字符串转换为 URL
        String urlString = "https://example.com";
        URL url = converterRegistry.convert(URL.class, urlString);
        // 进行业务操作
        System.out.println("用户 ID:" + userIdStr);
        System.out.println("URL:" + url);
    }
}
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 3. 自定义转换
Hutool 提供了许多默认的类型转换器,但在某些情况下,我们可能需要自定义转换逻辑。可以使用 ConverterRegistry.getInstance().putCustom() 方法来自定义类型转换。
# 3.1 自定义转换器
# 定义自定义转换器
首先,我们定义一个实现 Converter 接口的自定义转换器。在这个例子中,我们将自定义一个将对象转换为特定格式字符串的转换器。
public static class CustomConverter implements Converter<String> {
    @Override
    public String convert(Object value, String defaultValue) throws IllegalArgumentException {
        // 将对象转换为自定义格式的字符串
        return "Custom: " + value.toString();
    }
}
 2
3
4
5
6
7
API 使用说明
Converter接口:- 作用:提供一个标准的类型转换接口。通过实现这个接口,可以自定义任意类型的转换逻辑。
 - 语法:
public interface Converter<T> - 主要方法:
T convert(Object value, T defaultValue):- 作用:将 
value转换为类型T,如果转换失败则返回defaultValue。 - 语法:
T convert(Object value, T defaultValue) - 参数:
value:要转换的对象。defaultValue:转换失败时返回的默认值。
 - 返回值:转换后的对象,类型为 
T。 
- 作用:将 
 
 
# 注册转换器
然后,我们将自定义的转换器注册到 ConverterRegistry 中。
ConverterRegistry converterRegistry = ConverterRegistry.getInstance();
// 自定义 String 类型的转换器
converterRegistry.putCustom(String.class, CustomConverter.class);
 2
3
API 使用说明
putCustom(Class<T> type, Class<? extends Converter<T>> converterClass):- 作用:将自定义的转换器注册到 
ConverterRegistry中,以处理指定类型的转换。 - 语法:
<T> void putCustom(Class<T> type, Class<? extends Converter<T>> converterClass) - 参数:
type:目标类型的Class对象。例如,String.class。converterClass:自定义转换器的Class对象。例如,CustomConverter.class。
 - 返回值:无。
 
- 作用:将自定义的转换器注册到 
 
# 执行转换
最后,使用自定义转换器进行类型转换。
int a = 454553;
// 使用自定义转换器将整数 a 转换为字符串
String result = converterRegistry.convert(String.class, a);
Assert.assertEquals("Custom: 454553", result);
 2
3
4
API 使用说明
convert(Class<T> type, Object value):- 作用:使用已注册的转换器将 
value转换为指定的type类型。如果自定义转换器已经注册,会优先使用自定义转换器。 - 语法:
<T> T convert(Class<T> type, Object value) - 参数:
type:目标类型的Class对象。例如,String.class。value:要转换的对象。
 - 返回值:转换后的对象,类型为 
T。 
- 作用:使用已注册的转换器将 
 
# 3.2 实际开发中的应用
在实际开发中,自定义转换器可以用于将数据转换为特定格式,以便在系统中更容易使用。例如,将日志数据转换为特定格式的字符串用于输出或存储。
public class Application {
    public static void main(String[] args) {
        // 获取 ConverterRegistry 实例
        ConverterRegistry converterRegistry = ConverterRegistry.getInstance();
        // 自定义转换器
        converterRegistry.putCustom(String.class, CustomConverter.class);
        // 使用自定义转换器将整数转换为特定格式的字符串
        int logId = 67890;
        String formattedLogId = converterRegistry.convert(String.class, logId);
        // 输出或存储格式化后的日志 ID
        System.out.println("格式化后的日志 ID:" + formattedLogId);
    }
}
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 4. ConverterRegistry 单例和对象模式
 ConverterRegistry 提供了一个静态方法 getInstance() 来返回全局单例对象,这是推荐的使用方式。然而,如果你希望在某个限定范围内自定义转换,你也可以实例化 ConverterRegistry 对象。
# 4.1 示例代码
使用全局单例
ConverterRegistry converterRegistry = ConverterRegistry.getInstance(); // 获取全局单例1使用实例对象
ConverterRegistry customRegistry = new ConverterRegistry(); // 实例化对象1
API 使用说明
ConverterRegistry.getInstance():- 作用:返回 
ConverterRegistry的全局单例实例,保证全局只有一个实例用于类型转换。 - 语法:
ConverterRegistry.getInstance() - 参数:无。
 - 返回值:
ConverterRegistry的单例实例。 
- 作用:返回 
 new ConverterRegistry():- 作用:实例化一个新的 
ConverterRegistry对象,用于在特定范围内管理类型转换。 - 语法:
new ConverterRegistry() - 参数:无。
 - 返回值:一个新的 
ConverterRegistry实例。 
- 作用:实例化一个新的 
 
# 4.2 实际开发中的应用
在大多数情况下,使用 ConverterRegistry 的单例模式即可满足需求,尤其是在需要全局统一管理类型转换的场景中。对于局部的、特定场景的类型转换需求,可以实例化 ConverterRegistry 对象来管理这些转换逻辑。
public class Application {
    public static void main(String[] args) {
        // 使用全局单例进行通用转换
        ConverterRegistry globalRegistry = ConverterRegistry.getInstance();
        String globalResult = globalRegistry.convert(String.class, 123);
        // 使用自定义实例进行特定转换
        ConverterRegistry localRegistry = new ConverterRegistry();
        localRegistry.putCustom(String.class, CustomConverter.class);
        String localResult = localRegistry.convert(String.class, 456);
        System.out.println("全局转换结果:" + globalResult);
        System.out.println("局部转换结果:" + localResult);
    }
}
 2
3
4
5
6
7
8
9
10
11
12
13
14
15
总结
ConverterRegistry 提供了灵活的类型转换机制。通过自定义转换器,可以轻松实现特定的类型转换需求。结合单例和实例对象的使用方式,ConverterRegistry 可以很好地适应各种开发场景,简化类型转换逻辑,提高代码的可维护性和扩展性。