简体   繁体   English

Java 反射 generics - 通过在编译时传递参数进行转换?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM