通用工厂的Java通用不编译

时间:2011-02-02 16:13:23

标签: java generics guice

我有一个CacheListener<T>和一个CacheListenerLoader来实现CacheListener<Activity>

然后我有一个Provider<CacheListenerLoader> Guice,所以类型必须是CacheListenerLoader,所以google会生成正确的。

第4行无法编译:

CacheListenerLoader listTemp;
OurCacheListener<Activity> t2 = listTemp;
Provider<CacheListenerLoader> prov;
Provider<OurCacheListener<Activity>> temp = prov;

这很重要,因为我试图调用这个方法:

private <T> void put(Class<T> klass, Provider<OurCacheListener<T>> provider)

然后传递Provider和类类型的正确组合,以便在编译时保证类类型查找能够处理给定类的内容。

我将Activity.class和temp传递给我的put方法,并且工作正常并检查类型。关键是上面的第4行不起作用,看起来仿制药让我失败了,但我不确定为什么因为它是编译时的事情。

3 个答案:

答案 0 :(得分:6)

我将假设CacheListener是正确的类型,您要做的是将Provider<CacheListenerLoader>传递给put方法。

这里的问题是Provider<CacheListenerLoader>不是泛型世界中Provider<CacheListener<Activity>>的子类型。这就像你不能将List<Integer>分配给List<Number>类型...因为如果你这样做,你就可以将Double添加到List<Number>然后尝试从List<Integer>作为Integer检索它们,从而导致ClassCastException

当然,由于您无法向提供商添加任何内容,因此这不是问题。但你还是要告诉类型系统!您需要做的是将put的签名更改为:

private <T> void put(Class<T> clazz,
                     Provider<? extends CacheListener<T>> provider)

这表示您只想要任何可以返回CacheListener<T>内容的提供程序,并且您不需要能够调用任何尝试使用CacheListener<T>的方法。

答案 1 :(得分:1)

你需要使用一些通配符。哪些对我来说并不容易,因为你提供的代码很少,但我会说像

Provider<? extends OurCacheListener<Activity>> temp = prov;

供参考,请阅读

答案 2 :(得分:0)

你偶然发现了一个泛型限制:即使A扩展或实现B,提供者和提供者也不兼容。