2016-03-10 59 views
1

假设我们有一个具有两个子类A1,A2的类A. 假设我们有另一个类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(); 
    } 

    ... 
} 

我如何能实现类的getMyGenericList B所以我可以避免未经检查的铸造警告?

我想是这样的:

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

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

抱怨有没有办法做到这一点?

在此先感谢。

+3

'名单 a1list = b1.getMyGenericList:

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

现在,子类与具体参数A1定义();' –

+1

@RahulSharma注意到你不能用这个习惯用法将元素添加到列表中。 – Mena

+4

或者使B类通用:'B类 { 列表 myGenericList; }; 'B1类扩展B ' –

回答

4

使用当前定义B类的方法,myGenericList实例变量可以包含A的任何子类型的列表,因此在投射到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 

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

List<A1> a1list = b1.getMyGenericList(); 
+0

感谢@AlexR和rgettman的答案。今天我将测试 –

+0

按预期工作! –

0

你应该将你的一般定义,以一流水平如下:

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