如何推断泛型类型以避免未经检查的转换

时间:2016-03-10 16:08:30

标签: java generics

假设我们有一个A类,它有两个子类A1,A2。 假设我们有另一个B类,它也有两个子类,B1和B2:

class B{
  List<? extends A> myGenericList;

  B(List<? extends A> myGenericList){
    this.myGenericList = myGenericList;
  }

  public List<? extends A> getMyGenericList(){
    return myGenericList;
  }
}

class B1 extends B{
  B1(List<A1> a1List){
    super(a1List);
  }
}

class B2 extends B{
  B2(List<A2> a2List){
    super(a2List);
  }
}

现在,如果我们有这样的C1类:

class C1{
   ...

   public void doSomethingWithB1(B1 b1){
      List<A1> a1list = (List<A1>)b1.getMyGenericList();
   }

   ...
}

如何实现B类的getMyGenericList,以避免未经检查的转换警告?

我试过这样的事情:

public <T extends A> List<T> getMyGenericList() {
    return this.myGenericList;
}

但是编译器抱怨cannot convert from List<capture#3-of ? extends A> to List<T>

有什么办法吗?

提前致谢。

2 个答案:

答案 0 :(得分:4)

使用您已定义B类的当前方式,myGenericList实例变量可以保存A的任何子类型的List,因此在转换为{时,您获得的未经检查的强制转换警告{1}}是合理的。它可以是List<A1>List<A>

如果您真的不在乎列表中的List<A2>,则可以将其分配给A

List<? extends A>

但是如果你真的想从List<? extends A> a1list = b1.getMyGenericList(); 获得List<A1>,那么B1课程中的泛型就是你的答案。在类级别定义B,其上限为T。在整个班级中使用它来替换您的通配符。

A

class B<T extends A> { List<T> myGenericList; B(List<T> myGenericList){ this.myGenericList = myGenericList; } public List<T> getMyGenericList(){ return myGenericList; } } 的子类将分别定义B

T

这样你就可以消除未经检查的施法警告甚至根本不需要施放。

class B1 extends B<A1>  // rest of class is the same

class B2 extends B<A2>  // rest of class is the same

答案 1 :(得分:0)

您应该将通用定义移动到类级别,如下所示:

class B<T extends A> {
  List<T> myGenericList;

  B(List<T> myGenericList){
    this.myGenericList = myGenericList;
  }

  public List<T> getMyGenericList(){
    return myGenericList;
  }
}

现在使用具体参数A1

定义子类
class B1 extends B<A1>{
  B1(List<A1> a1List){
    super(a1List);
  }
}