Java泛型工厂通过Class参数+反射实现动态创建,核心是<T> T create(Class<T> clazz)方法,利用编译期类型推断保障安全,规避泛型擦除限制。

Java 中用泛型实现工厂模式的动态创建,核心是**让工厂能根据类型参数自动推导并创建对应实例**,避免重复写一堆 if-else 或 switch,同时保持编译期类型安全。关键不在于“泛型本身创建对象”,而在于**结合 Class 对象、反射和泛型类型擦除的应对策略**。
泛型工厂接口:定义统一创建契约
先定义一个泛型工厂接口,声明“我能创建 T 类型的对象”:
public interface GenericFactory<T> {
T create();
}
这个接口本身不解决“如何动态指定 T”,只是为不同实现提供一致签名。真正动态的部分在具体工厂或调用方。
基于 Class 参数的泛型工厂(推荐)
最实用、类型安全且无需强转的方式:把 Class<t></t> 作为参数传入,利用反射 + 泛型方法推断:
立即学习“Java免费学习笔记(深入)”;
- 工厂方法声明为
<T> T create(Class<T> clazz),调用时编译器能根据传入的 Class 自动推断返回类型 - 要求目标类有无参构造器(或用其他方式处理构造逻辑)
- 可封装成工具类或单例工厂
public class SimpleGenericFactory {
public <T> T create(Class<T> clazz) {
try {
return clazz.getDeclaredConstructor().newInstance();
} catch (Exception e) {
throw new RuntimeException("Cannot instantiate " + clazz.getName(), e);
}
}
}
// 使用示例
SimpleGenericFactory factory = new SimpleGenericFactory();
String str = factory.create(String.class); // 返回 String,无需强转
List<Integer> list = factory.create(ArrayList.class); // 返回 ArrayList<Integer>
带注册机制的泛型工厂(适合多类型、需定制初始化)
当不同类型的创建逻辑差异大(比如需要传参、依赖注入、缓存单例等),可用 Map 注册构造器函数:
- 用
Class<T>作 key,Supplier<T>作 value - 泛型方法
<T> T getInstance(Class<T> type)查找并执行构造器 - 注册时明确类型,使用时由 Class 参数驱动泛型推断
public class RegistryGenericFactory {
private final Map<Class<?>, Supplier<?>> registry = new HashMap<>();
public <T> void register(Class<T> type, Supplier<T> creator) {
registry.put(type, creator);
}
@SuppressWarnings("unchecked")
public <T> T getInstance(Class<T> type) {
Supplier<T> creator = (Supplier<T>) registry.get(type);
if (creator == null) throw new IllegalArgumentException("No creator registered for " + type);
return creator.get();
}
}
// 使用
RegistryGenericFactory factory = new RegistryGenericFactory();
factory.register(Connection.class, () -> DriverManager.getConnection("jdbc:h2:mem:"));
factory.register(UserService.class, () -> new UserServiceImpl(new UserDao()));
Connection conn = factory.getInstance(Connection.class); // 类型安全
UserService service = factory.getInstance(UserService.class);
注意泛型擦除与类型安全边界
Java 运行时没有泛型信息,所以不能直接写 new T() 或 T.class。所有“动态创建 T”的方案都必须显式获得 Class<T> 或等效元数据:
- 不要试图在泛型类内部靠
this.getClass().getTypeParameters()获取 T 的 Class —— 它只返回 TypeVariable,无法用于 newInstance - 如果必须隐藏 Class 参数,可用工厂子类在构造时传入 Class(如
new StringFactory(String.class)),但会增加类数量 - Lombok 的
@RequiredArgsConstructor(onConstructor_ = {@SuppressWarnings("unchecked")})可简化带 Class 参数的构造
不复杂但容易忽略。


















