泛型接口实现分保留类型参数和指定具体类型两种:需复用多类型时保留泛型,如GenericConverter<T>;业务单一明确时固化类型,如UserRepo implements Repository<User>;还可混合使用,如JsonService<R> extends BaseService<String, R>。

泛型接口的实现方式主要分两种:一种是在实现类中保留类型参数(继续泛型化),另一种是直接指定具体类型(固化类型)。选哪一种,关键看这个实现类后续是否需要支持多种类型,以及它在整个架构中承担的是通用契约角色,还是面向特定业务的固定职责。
需要复用、扩展或适配多类型时——保留类型参数
当接口定义了通用行为(比如数据转换、事件处理、策略执行),而不同模块会传入不同类型的输入输出,就该让实现类也保持泛型。这样一份代码能服务 String、User、Order 等任意类型,避免重复实现。
- 典型例子:一个通用 JSON 转换器接口
Converter<T>,实现类GenericConverter<T>可以同时用于GenericConverter<String>和GenericConverter<Product> - 适合放在工具包、基础框架层,被多个业务模块引用
- 创建实例时才绑定类型,灵活性高,但调用方需明确提供类型实参
业务边界清晰、只服务单一类型时——指定具体类型
如果某个实现类从设计之初就只为某一种业务实体服务(比如用户管理模块里的 UserRepository),没必要开放泛型能力。直接在 implements 语句中写死类型,既简化代码,又增强语义可读性,还能防止误用。
- 典型例子:DAO 层实现
class UserRepo implements Repository<User>,所有方法天然只操作 User 对象 - 适合垂直业务模块内部,类型稳定、职责聚焦
- 编译期约束更严格,IDE 提示更精准,维护成本更低
混合使用:接口泛型 + 实现类部分固化
有些场景可以折中处理。比如父接口定义为 Service<T, R>(输入 T、输出 R),子类继承时固定输入类型为 String,但保留输出类型 R 泛型:class JsonService<R> extends BaseService<String, R>。这种做法兼顾复用性与约束力。
- 常见于配置驱动型服务,如统一响应封装、协议解析器
- 需注意类型参数传递链不能断裂,否则编译报错
- 建议配合
extends或super通配符做安全限定,避免运行时类型擦除带来的隐患
不复杂但容易忽略的是:保留泛型不是为了“看起来高级”,而是为真正需要多态支撑的场景留出空间;而固化类型也不是偷懒,是把类型契约显式落在代码里,让意图一目了然。

















