Java Generics限制或错误用法?

Raz*_*van 12 java generics

我有一个类代表一对相同类型的两个值(类型可以是任何特定类型的集合):

  public class Pair<E extends AClass>{
      private E var1;
      private E var2; 
  }
Run Code Online (Sandbox Code Playgroud)

这个类由框架使用,因此它需要一个无参构造函数,我必须在其中实例化2个变量(var1,var2):

  public class Pair<E extends AClass>{
      private E var1;
      private E var2; 

      public Pair(){
           var1 = invoke constructor of type E; 
           var2 = invoke constructor of type E 
      }
  }
Run Code Online (Sandbox Code Playgroud)

这里显然有很多问题:

  1. 为了实例化变量,我应该以某种方式知道它的确切类型并调用该特定类型的构造函数; 在最好的情况下,这意味着在构造函数中有一个非常大的if else语句,如:

     public Pair(){
           if(var1 instanceof SpecificType1){
              var1 = new SpecificType1(); 
              var2 = new SpecificType2();
           }
      }
    
    Run Code Online (Sandbox Code Playgroud)
  2. 即使我如上所述,我也会遇到一些问题,因为var1被声明为E类,我在尝试实例化SpecficType1并将结果对象分配给var1/var2时会遇到类型不匹配错误.为了使它工作,我必须转向E:

       var1 = (E)new SpecificType1();
    
    Run Code Online (Sandbox Code Playgroud)

但是这会破坏编译时类型检查,因为我正在尝试将特定类型转换为泛型类型.

这是Java中Generics的限制还是这个场景对于使用Generics来说是一个糟糕的局面?

Mik*_*uel 7

为了实例化变量,我应该以某种方式知道它的确切类型并调用该特定类型的构造函数; 在最好的情况下,这意味着在构造函数中有一个非常大的if else语句,如:

在此之前你会遇到问题.

   if(var1 instanceof SpecificType1){
      var1 = new SpecificType1(); 
      var2 = new SpecificType2();
   }
Run Code Online (Sandbox Code Playgroud)

var1就是null在这一点上,所以var1 instanceof Tfalse对所有T.


Java泛型的一个限制是擦除了泛型类型参数,因此无法从零参数构造函数中反映出类型参数.

调用者提供一些背景来告诉你如何初始化var1var2,并提供这方面的典型方式是通过构造函数参数.


您最好的选择可能是让var1var2开始null然后延迟初始化,直到您可以获得所需的上下文.

也许

void init(Class<E> type) {
  if (type.isAssignableFrom(ConcreteType1.class)) {
    var1 = type.cast(new ConcreteType1(...));
    var2 = type.cast(new ConcreteType1(...));
  } else { /* other branches */ }
}
Run Code Online (Sandbox Code Playgroud)

这是不完美的,因为你仍然无法区分E extends List<String>,E extends List<Number>但它可能足够你的情况,并且该.cast方法将为您提供类型安全的演员E.


或者,Guava,Guice和相关库提供类似Supplier<E>接口的东西,它可以在init方法中派上用场.