简体   繁体   English

无法从非通用子类转换为通用超类

[英]Cannot convert from not generic subclass to generic superclass

I'm trying to get interface instance depending on what type T is. 我试图根据类型T获得接口实例。 Place or something else that extends BaseDictionary. 放置或扩展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>{}

And I get 我得到

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

or 要么

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

if I cast it like above. 如果我像上面那样投

Can you explain why do compile error and warning occur? 您能解释为什么发生编译错误和警告吗?

It will be called here 它会在这里被称为

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

I've tried to find answer here and in google but no success.I would appreciate any help. 我试图在这里和Google中找到答案,但没有成功。我将不胜感激。 Now I think like this 现在我想这样

There is no helper method to work around the problem, because the code is fundamentally wrong. 没有解决此问题的辅助方法,因为代码根本上是错误的。

Thanks in advance. 提前致谢。

This more concrete example illustrates your problem which is one of type parameter variance . 这个更具体的例子说明了您的问题,它是类型参数差异之一

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
}

so a List<String> is not a List<Object> although it is a List<? extends Object> 所以List<String>不是List<Object>尽管它是List<? extends Object> List<? extends Object> . List<? extends Object>


In your specific instance you can't cast 在您的特定情况下,您无法投放

PlaceDataSource to IDictionaryDataSource<T> PlaceDataSourceIDictionaryDataSource<T>

PlaceDataSource is an IDictionaryDataSource<Place> , but the only thing we know about <T> is that it extends BaseDictionary which is a super-class of BaseDictionary . PlaceDataSource IDictionaryDataSource<Place> ,但我们知道的唯一的事情<T>是它扩展BaseDictionary这是一个超一流的BaseDictionary

So you can cast a PlaceDataSource to 因此,您可以将PlaceDataSource

  1. an IDictionaryDataSource<Place> or to IDictionaryDataSource<Place>
  2. an IDictionaryDataSource<? super Place> 一个IDictionaryDataSource<? super Place> IDictionaryDataSource<? super Place> or to IDictionaryDataSource<? super Place>
  3. an IDictionaryDataSource<? extends BaseDictionary> 一个IDictionaryDataSource<? extends BaseDictionary> IDictionaryDataSource<? extends BaseDictionary>

but not to an IDictionaryDataSource<T> because T is not guaranteed to be Place , and doing so would lead to a mismatch between the actual type parameter Place and the formal type parameter T . 而不是IDictionaryDataSource<T>因为不能保证TPlace ,否则将导致实际类型参数Place和形式类型参数T不匹配。

That is not secure implementation and it is dangerous to cast because ( Place.class.isAssignableFrom(clazz) saves you here): 那不是安全的实现,并且因为( Place.class.isAssignableFrom(clazz)在这里节省了您的Place.class.isAssignableFrom(clazz) ,所以进行转换很危险:

T is a generic type and you're replacing it with definite Place . T是泛型类型,您将其替换为确定Place

What if I have 如果我有怎么办

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

And then I invoke getEntityDataSourceInstance with Home class but get PlaceDataSource which cannot be cast to HomeDataSource (IDictionaryDataSource) which I expect. 然后,我用Home类调用getEntityDataSourceInstance ,但是得到PlaceDataSource ,它不能转换为我期望的HomeDataSource (IDictionaryDataSource)。 So I'll end up having ClassCastException . 因此,我最终将遇到ClassCastException

It looks like getEntityDataSourceInstance should be an instance method in the BaseDictionary class, not a static method. 看起来getEntityDataSourceInstance应该是BaseDictionary类中的实例方法,而不是静态方法。

A subclass will know which type of DictionaryDataSource to create. 子类将知道要创建哪种DictionaryDataSource类型。

尝试@SuppressWarnings(“ unchecked”)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM