存在以下情况:
给出了一个类,其中有一个泛型字段。是否可以在运行时用T
的实例实例化该字段?
class Root<T>{
T var;
Root(){
//instantiate var with an instance of T here
}
}
如果您有一个扩展Root<T>
并在其extends
子句中设置类型参数的类,那么可以使用getGenericSuperclass((来挖掘它。例如,Guice使用这种方法向注入的类提供类型参数信息。
否则,最好的办法是传递一个Class<T>
实例作为构造函数参数并使用它。这也会导致代码更简单,尽管类的每个实例化都有更多的样板。
否。
Java使用类型擦除,因此在运行时不存在泛型参数。
除非在运行时为您提供T
的实例,否则由于java类型的擦除,答案是否定的。在运行时,T实际上被Object替换,因此不存在必要的信息。这就是像List.toArray这样的函数需要传入类型化数组才能接收类型化结果的原因。
在运行时无法知道T
的类型,因为它在编译时被擦除。
但是,您可以向Class<T>
类型的构造函数添加一个新参数。编译器将确保传递的对象是与您为Root
实例指定的T
类型相对应的Class
实例。在构造函数中,您可以使用反射来创建一个新的T实例:
class Root<T> {
T var;
public Root(Class<T> klass) {
var = klass.newInstance();
}
}
这假设您的T
类型有一个默认构造函数。
否。如果您确实需要此功能,则需要在构造函数中传递类型。
像这样:
class Root<T> {
private T var;
public Root(Class<T> type) {
var = type.newInstance();
}
}
这将通过反射创建一个实例。只有当传入的类具有默认构造函数时,它才会起作用。否则,您将需要扩展示例。