无法从非泛型子类转换为泛型超类

时间:2013-08-09 12:13:18

标签: java

我正在尝试根据T的类型获取接口实例。放置BaseDictionary的地方或其他东西。

public static <T extends BaseDictionary> IDictionaryDataSource<T> getEntityDataSourceInstance(Class<T> clazz,
        Context cxt) {
    if (Place.class.isAssignableFrom(clazz)) return (IDictionaryDataSource<T>) new PlaceDataSource(cxt);
            //here some other types, same lines

    return null;
}

public abstract class BaseDictionary{}

public class Place extends BaseDictionary{}

public interface IDictionaryDataSource<T extends BaseDictionary>{}

public abstract class BaseDictionaryDataSource<T extends BaseDictionary> implements   IDictionaryDataSource<T>{}

public class PlaceDataSource extends BaseDictionaryDataSource<Place>{}

我得到了

Type mismatch: cannot convert from PlaceDataSource to IDictionaryDataSource<T>

Type safety: Unchecked cast from PlaceDataSource to IDictionaryDataSource<T>

如果我像上面那样投射它。

你能解释为什么会出现编译错误和警告吗?

这里将被称为

public static <T extends BaseDictionary> DictionaryElementPickerFragment<T> newInstance(Class<T> clazz, Context cxt){
     //somecode here
     fragment.setDataSource(DictUtils.getEntityDataSourceInstance(clazz, cxt));
}

我试图在这里和谷歌找到答案,但没有成功。我将不胜感激任何帮助。 现在我想像这样

  

没有帮助方法来解决这个问题,因为代码根本就是错误的。

提前致谢。

4 个答案:

答案 0 :(得分:1)

这个更具体的例子说明了你的问题,它是类型参数方差之一。

void foo(List<String> stringList, Integer anInteger) {
  List<Object> objList = (List<Object>) stringList;
  objList.add(anInteger);  // Violation -- adding an object to a list of strings
                           // could cause someone getting a "String" to get an
                           // Integer stead
}

所以List<String>不是List<Object>,尽管它是List<? extends Object>


在您的特定实例中,您无法投射

  

PlaceDataSourceIDictionaryDataSource<T>

PlaceDataSource IDictionaryDataSource<Place>,但我们对<T>唯一了解的是它扩展了BaseDictionary这是一个超类BaseDictionary

所以你可以将PlaceDataSource投射到

  1. IDictionaryDataSource<Place>
  2. IDictionaryDataSource<? super Place>
  3. IDictionaryDataSource<? extends BaseDictionary>
  4. 但不是IDictionaryDataSource<T>,因为T不能保证为Place,这样做会导致实际类型参数Place与正式参数不匹配类型参数T

答案 1 :(得分:0)

这不是安全的实施,因为(Place.class.isAssignableFrom(clazz)将你保存在这里)而施展是危险的:

T是一种通用类型,您将其替换为明确的Place

如果我有

怎么办?
public class Home extends BaseDictionary{}
public class HomeDataSource extends BaseDictionaryDataSource<Home>{}

然后我使用getEntityDataSourceInstance类调用Home,但得到PlaceDataSource,它不能转换为我期望的HomeDataSource(IDictionaryDataSource)。所以我最终会得到ClassCastException

答案 2 :(得分:0)

看起来getEntityDataSourceInstance应该是BaseDictionary类中的实例方法,而不是静态方法。

子类将知道要创建的DictionaryDataSource类型。

答案 3 :(得分:-3)

尝试@SuppressWarnings(“未选中”)