java 泛型不能 new t() 是因为 java 采用类型擦除机制,在编译后泛型类型参数 t 会被替换为它的上界(默认是 object),导致运行时无法获知具体的类信息,从而无法调用构造函数。要解决这个问题,必须在创建对象时显式传入 class<t></t> 对象,利用反射来实例化。

为什么泛型类型参数在运行时会丢失?
因为 Java 泛型是基于类型擦除实现的,编译器在编译阶段会检查类型安全,但在生成字节码时会将所有泛型类型参数擦除为它们的边界类型。这意味着在运行时,JVM 根本不知道 T 具体代表哪个类,因此无法执行 new T() 这种需要知道确切类信息的操作。

import java.lang.reflect.Constructor;
public class GenericFactory {
private final Class<T> clazz;
public GenericFactory(Class<T> clazz) {
this.clazz = clazz;
}
public T createInstance() {
try {
Constructor<T> constructor = clazz.getDeclaredConstructor();
return constructor.newInstance();
} catch (Exception e) {
throw new RuntimeException("Failed to create instance", e);
}
}
}上述代码展示了如何通过保存 Class<t></t> 并在运行时使用反射来获取无参构造函数并创建实例。这是解决该问题的标准做法。
立即学习“Java免费学习笔记(深入)”;
如何在使用泛型的工厂模式中正确实例化对象?
在工厂模式或需要内部创建泛型对象的场景中,必须将 Class<t></t> 作为构造参数传入,并在方法内部通过反射完成实例化。这样可以确保在运行时能够动态地创建正确的对象类型。

public class User {
private String name;
public User() { this.name = "default"; }
@Override
public String toString() { return "User{name='" + name + "'}"; }
}
public class Main {
public static void main(String[] args) {
GenericFactory<User> factory = new GenericFactory<>(User.class);
User user = factory.createInstance();
System.out.println(user); // 输出: User{name='default'}
}
}运行上述代码,控制台将输出 User{name='default'},证明通过传入 Class 对象并使用反射可以成功实例化泛型类型。
如果泛型类没有无参构造函数会发生什么?
如果指定的泛型类型 T 没有无参构造函数,上述反射方式会抛出 NoSuchMethodException 或 InstantiationException。此时需要修改 GenericFactory 以支持带参数的构造函数,或者在调用 getDeclaredConstructor 时传入具体的参数类型数组,并在 newInstance 时提供对应的参数值。


















