1. 概述

ClassToInstanceMap<B> 是一种特殊类型的 Map,它将类(Class)与对应的实例(Instance)关联起来。它确保所有键和值都是上界类型 B 的子类型。

ClassToInstanceMap 扩展了 Java 的 Map 接口,并额外提供了两个方法:T getInstance(Class<T>)T putInstance(Class<T>, T)。这个 Map 的最大优势在于,可以通过这两个方法执行类型安全的操作,彻底避免强制类型转换的麻烦。

在本教程中,我们将展示如何使用 Google Guava 的 ClassToInstanceMap 接口及其实现类。

2. Google Guava 的 ClassToInstanceMap

先看看如何使用这个工具类。首先在 pom.xml 中添加 Guava 库依赖:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>32.1.3-jre</version>
</dependency>

最新版本可查看 这里

ClassToInstanceMap 接口有两种实现:可变版本不可变版本。我们分别来看。

3. 创建不可变实例 ImmutableClassToInstanceMap

创建 ImmutableClassToInstanceMap 实例有几种方式:

使用 of() 创建空 Map

ImmutableClassToInstanceMap.of()

使用 of(Class<T> type, T value) 创建单元素 Map

ImmutableClassToInstanceMap.of(Save.class, new Save());

使用 copyOf() 复制已有 Map

ImmutableClassToInstanceMap.copyOf(someMap)

使用 Builder 模式(推荐多元素场景):

ImmutableClassToInstanceMap.<Action>builder()
  .put(Save.class, new Save())
  .put(Open.class, new Open())
  .put(Delete.class, new Delete())
  .build();

⚠️ 注意:不可变 Map 创建后不能修改,任何修改操作都会抛出 UnsupportedOperationException

4. 创建可变实例 MutableClassToInstanceMap

创建 MutableClassToInstanceMap 实例的方式更简单粗暴:

使用 create() 创建基于 HashMap 的实例

MutableClassToInstanceMap.create();

使用 create(Map<Class<? extends B>, B> backingMap) 指定底层 Map

MutableClassToInstanceMap.create(new HashMap());

踩坑提示:如果传入的 Map 非空,Guava 会直接使用它作为底层存储,可能导致初始数据不符合类型约束!

5. 核心方法使用

ClassToInstanceMap 在标准 Map 接口基础上增加了两个类型安全的方法:

5.1 类型安全的获取:<T extends B> T getInstance(Class<T> type)

对比传统方式:

// ❌ 传统方式需要强制转换
Action openAction = (Action) map.get(Open.class);

// ✅ 类型安全方式
Delete deleteAction = map.getInstance(Delete.class);

5.2 类型安全的存入:<T extends B> T putInstance(Class<T> type, @Nullable T value)

对比传统方式:

// ❌ 传统方式无类型检查
Action newOpen = (Action) map.put(Open.class, new Open());

// ✅ 类型安全方式
Delete newDelete = map.putInstance(Delete.class, new Delete());

核心优势:编译时就能发现类型错误,彻底避免运行时的 ClassCastException

6. 总结

ClassToInstanceMap 是 Guava 提供的一个实用工具,特别适合需要按类类型管理实例的场景。它的核心价值在于:

  1. 类型安全:通过泛型约束避免强制转换
  2. API 简洁getInstance/putInstance 方法语义清晰
  3. 实现灵活:提供可变/不可变两种实现

实际应用场景包括:

  • 依赖注入容器
  • 策略模式实现
  • 插件系统架构

完整示例代码可在 GitHub 项目 中查看。


原始标题:Guide to Guava ClassToInstanceMap