Java泛型类不能用new T()创建实例,根本原因是类型擦除;工厂模式需显式传入Class对象或Supplier来动态创建实例,常用方式为Class参数+泛型方法推断,或Supplier委托,或注册机制。

Java 中泛型类不能直接用 new T() 创建实例,根本原因是类型擦除——编译后泛型参数 T 已不存在,JVM 不知道该构造哪个具体类型。工厂模式要实现“动态创建泛型类对应实例”,关键不是让泛型自己造对象,而是把**类型信息以 Class 对象或构造逻辑的形式显式传进来**,再结合反射或函数式接口完成创建。
用 Class 参数 + 泛型方法推断(最常用)
这是兼顾类型安全、简洁性和通用性的首选方式。工厂方法声明为 <t> T create(Class<t> clazz)</t></t>,调用时编译器能根据传入的 String.class 或 ArrayList.class 自动推断返回类型,无需强转。
- 要求目标类有无参构造器(否则需扩展支持带参构造)
- 内部用
clazz.getDeclaredConstructor().newInstance()安全创建,比已废弃的newInstance()更健壮 - 可封装为工具类、单例或 Spring Bean,方便复用
用 Supplier 委托创建逻辑(最灵活)
当创建过程复杂(如需传参、依赖注入、缓存、校验),把构造行为交给调用方更合理。工厂只负责接收并执行 Supplier<t></t>:
在调试 Java 后端 API 故障时使用此技能,尤其适用于以下任务:分析日志、跨 Controller、Service 和 Mapper 层追踪请求、定位异常根因、检查 SQL 执行或参数流转,以及生成简洁的诊断结论与修复方案。
public static <t> T create(Supplier<t> supplier) { return supplier.get(); }</t></t>- 调用方用 Lambda 或方法引用提供具体逻辑:
create(() -> new Person("Tom", 25))或create(HashMap::new) - 完全绕过反射,类型安全、无异常检查、支持任意构造方式
带注册机制的泛型工厂(适合多类型定制)
如果不同类型的初始化逻辑差异大(比如有的要单例、有的要连接池、有的要加载配置),可用 Map 注册构造器:
立即学习“Java免费学习笔记(深入)”;
- 用
Class<t></t>作 key,Supplier<t></t>作 value - 注册示例:
registry.put(ServiceA.class, () -> new ServiceA(config)) - 获取时:
public <t> T getInstance(Class<t> type) { return registry.get(type).get(); }</t></t> - 类型推断依然由传入的
Class驱动,调用端保持干净
不推荐的方式:泛型类自身硬编码创建逻辑
像 class GenericFactory<t> { public T create() { return new T(); } }</t> 是非法的——编译直接报错。试图在泛型类内部“猜”类型或依赖 Class<t></t> 字段存储又容易出错(如子类未正确传递类型)。真正需要的是**把类型选择权和构造权交给调用上下文**,而不是塞进泛型类定义里。

















