局部变量vs setter在函数中使用泛型

时间:2014-07-05 21:20:30

标签: java generics

我有一个ITransportable接口,强制实现它的类有两个方法,一个用于根据“this”生成一个对象,另一个用于从对象加载“this”。事实上,我正在使用“transports”对象来隐藏用户的基础类,因此每个“可传输”的类,在此示例中“ItemDetalle”都具有相应的传输类。 GenericTransport类实现了一些泛型方法,用于使代码更具可读性,所有传输类都是从它派生的。

public interface ITransportable<T> { 
  public T getTransport();
  public <U extends ITransportable<T>> U loadFromTransport(T transport);
}

public class GenericTransport {
  [...]
  public static <T extends ITransportable<U>,U extends GenericTransport> T loadFromTransport(U transport) {
    try {
      Method loadFromTransport=transport.getClass().getMethod("loadFromTransport");
      T result = (T) loadFromTransport.invoke(transport);
      return result;
    } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
      Logger.getLogger(GenericTransport.class.getName()).log(Level.SEVERE, null, ex);
    }
    return null;
  }

  public static <T,U extends GenericTransport> LinkedList<T> loadFromTransport(List<U> list) {
    if (list==null) return null;
    LinkedList<T> ll=new LinkedList<>();
    for (U element : list) ll.add((T) GenericTransport.loadFromTransport(element));
    return ll;
  }

}

这里有两个“twin”类,ItemDetalle类和ItemDetalleTransport

public ItemDetalleTransport extends GenericTransport {
  [...]
}

public class ItemDetalle implements ITransportable<ItemDetalleTransport> {
  public ItemDetalleTransport getTransport() {
    [...]
  }
  public void loadFromTransport(ItemDetalleTransport t) {
    [...]
  }
}

并且有一个我用于实验的课程:

public class otherClass {
  protected LinkedList<ItemDetalle> det
  public void setDet(LinkedList<ItemDetalle> det) {
    this.det=det;
  }
  [...]
  public void test1(ItemDetalleTransport t) {
    ItemDetalle det = GenericTransport.loadFromTransport(t);    
  }
  public void test2(LinkedList<ItemDetalleTransport> t) {
    LinkedList<ItemDetalle> localDet = GenericTransport.loadFromTransport(t);    
    this.setDet(localDet);
  }
  public void test3(LinkedList<ItemDetalleTransport> t) {
    this.det = GenericTransport.loadFromTransport(t);    
  }
  public void test4(LinkedList<ItemDetalleTransport> t) {
    this.setDet(GenericTransport.loadFromTransport(t));
  }
  [...]
}

函数“test4”不起作用,声称对象的LinkedList无法转换为ItemDetalle的LinkedList。 我知道这不是一个很大的问题,但我很好奇,有人可以解释原因吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

在Java中,泛型是不变的,我将用一个例子来解释。

假设您有一个课程Parent和另一个课程Child,其范围为Parent。泛型不变意味着List<Child>不会被视为List<Parent>,而不像数组(Child[] arr instanceof Parent[])。

泛型不变的原因在于它是通过擦除实现的 - 这意味着它们仅在编译时强制执行类型约束并在运行时丢弃其类型信息(同样,与数组不同)。由于泛型不能在运行时强制执行它们的类型,并且为了安全使用 - 泛型变得不变。

<强>附录: 由于以下评论中的讨论,阅读thisthis告诉我们,数组是协变的,作为类型安全与使程序更具多态性的可能性之间的权衡。引入泛型时不需要进行权衡,因为随之而来的是带有协方差表达式的通配符。非常感谢@ user3580294!