4

我正在尝试根据 T 的类型获取接口实例。Place 或其他扩展 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

4 回答 4

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
}

所以 aList<String>不是 aList<Object>虽然它是 a List<? extends Object>


在您的特定情况下,您无法投射

PlaceDataSourceIDictionaryDataSource<T>

PlaceDataSource IDictionaryDataSource<Place>,但我们唯一知道<T>的是它扩展BaseDictionary了 ,它是 的超类BaseDictionary

PlaceDataSource所以你可以投到

  1. 一个IDictionaryDataSource<Place>或到
  2. 一个IDictionaryDataSource<? super Place>或到
  3. 一个IDictionaryDataSource<? extends BaseDictionary>

但不是IDictionaryDataSource<T>因为T不保证是Place,这样做会导致实际类型参数Place和正式类型参数不匹配T

于 2013-08-09T20:27:41.730 回答
0

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

子类将知道DictionaryDataSource要创建哪种类型。

于 2013-08-09T20:13:27.120 回答
0

这不是安全的实现,并且强制转换很危险,因为(Place.class.isAssignableFrom(clazz)将您保存在这里):

T是一个泛型类型,你用 definite 替换它Place

如果我有

public class Home extends BaseDictionary{}
public class HomeDataSource extends BaseDictionaryDataSource<Home>{}

然后我getEntityDataSourceInstanceHome类调用,但 getPlaceDataSource不能转换为HomeDataSource我期望的 (IDictionaryDataSource) 。所以我最终会拥有ClassCastException.

于 2013-08-09T12:21:06.853 回答
-3

试试@SuppressWarnings("unchecked")

于 2013-08-09T12:40:52.233 回答