2016-02-26 95 views
0

我在(B)行得到编译错误“AlphaData无法通过方法调用转换转换为CAP#1”。我的解决方法是将line(A)处的indexOf()的签名更改为Object类型而不是T.但是,然后我失去了类型检查。此外,如果“数据”也被声明为BetaData类型,我想让B行工作。有没有办法做我想要的?Java:使用具有通配符类型参数的类函数

public class Test 
{ 
    class AlphaData {} // base class for data 

    class BetaData extends AlphaData {} // subclass for data 

    abstract class BasicAdapter<T> // a generic adapter 
    { 
    abstract int indexOf (T item); //(A) 
    } 

    class BetaAdapter extends BasicAdapter<BetaData> // adapter subclass with binding 
    { 
    int indexOf (BetaData item) { return 0; } 
    } 


    BasicAdapter<? extends AlphaData> adapter = null; 

    Test() 
    { 
    AlphaData data = null; 
    int index = adapter.indexOf (data); //(B) -- compile error here 
    } 
} 
+2

你如何实例化适配器? –

+0

写入的示例只允许一个实例:new BetaAdapter()。但是它需要为BasicAdapter的其他子类以及BetaAdatper的子类工作。 –

回答

3

adapter.indexOf不能安全地传递了一个AlphaData,因为它可能具体是BasicAdapter<BetaData>;尽管data具体可以是BetaData的实例,但它可以是普通的AlphaData或任何其他不相关的子类AlphaData

缩写要记住的是佩奇

  • 生产者extend
  • 消费者super

你想adapter消耗AlphaData,所以你需要一个BasicAdapter<? super AlphaData>

2

这是正常现象。

BasicAdapter<? extends AlphaData> adapter = null 

声明adapter是某种类型的扩展AlphaDataBasicAdapter但它可以是任何类型的,所以T = any type that extends AlphaData。因此,当你调用

AlphaData data = null; 
int index = adapter.indexOf (data); //(B) -- compile error here 

你给一个AlphaData参数,所以它不符合“的东西是一个AlphaData”:这可能是例如BetaData

如果你想让它对于任何AlphaData工作,只需使用:

BasicAdapter<AlphaData> adapter = null; 

不使用通配符,或

BasicAdapter<? super AlphaData> adapter = null; 

这将编译如果dataAlphaDataBetaData