[英]Java reflections generics - cast by passing a parameter at compile time?
There is a following situation:有以下情况:
A class is given, with a generic field in it.给出了一个 class,其中有一个通用字段。 Is it possible to instantiate the field at runtime with an instance of T
?是否可以在运行时使用T
实例实例化该字段?
class Root<T>{
T var;
Root(){
//instantiate var with an instance of T here
}
}
If you have a class which extends Root<T>
and sets the type parameter in its extends
clause, then it's possible to dig it out using getGenericSuperclass() .如果您有一个 class 扩展Root<T>
并在其extends
子句中设置类型参数,则可以使用getGenericSuperclass()将其挖掘出来。 For example Guice uses this approach to provide type parameter information to the injected classes.例如, Guice 使用这种方法为注入的类提供类型参数信息。
Otherwise, the best bet is to pass a Class<T>
instance as constructor parameter and use it.否则,最好的办法是将Class<T>
实例作为构造函数参数传递并使用它。 This will also result in simpler code, though a bit more boilerplate for each instantiation of the class.这也将导致代码更简单,尽管 class 的每个实例化都有更多样板。
No.不。
Java uses type erasure , so the generic parameter does not exist at runtime. Java 使用类型擦除,因此在运行时不存在泛型参数。
Unless you are given an instance of T
at runtime, the answer is no because of java type erasure .除非在运行时为您提供T
的实例,否则答案是否定的,因为java 类型擦除。 At runtime T is actually replaced with Object so the necessary information doesn't exist.在运行时 T 实际上被替换为 Object 因此不存在必要的信息。 This is the reason that functions like List.toArray require you to pass in a typed array in order to receive a typed result.这就是像 List.toArray 这样的函数需要您传入类型化数组才能接收类型化结果的原因。
There is no way to know the type of T
at runtime since it is erased at compile time.在运行时无法知道T
的类型,因为它在编译时被擦除。
However, you can add a new parameter to your constructor of type Class<T>
.但是,您可以向Class<T>
类型的构造函数添加一个新参数。 The compiler will ensure that the object passed is a Class
instance corresponding to the T
type you specified for your Root
instance.编译器将确保传递的 object 是一个Class
实例,对应于您为Root
实例指定的T
类型。 In your constructor, you can then use reflection to create a new T instance:在您的构造函数中,您可以使用反射来创建一个新的 T 实例:
class Root<T> {
T var;
public Root(Class<T> klass) {
var = klass.newInstance();
}
}
This supposes your T
type has a default constructor.这假设您的T
类型具有默认构造函数。
No. If you really need this functionality you will need to pass in the type in your constructor.不,如果你真的需要这个功能,你需要在你的构造函数中传入类型。
Like this:像这样:
class Root<T> {
private T var;
public Root(Class<T> type) {
var = type.newInstance();
}
}
This will create an instance via reflection.这将通过反射创建一个实例。 It will only work if the class passed in has a default constructor.仅当传入的 class 具有默认构造函数时,它才会起作用。 Otherwise you'll need to extend the example.否则,您需要扩展示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.