Java通配符强制转换为子类型

时间:2016-08-29 09:56:11

标签: java generics wildcard

由于某些历史原因,我必须使用带有两个通配符参数的抽象类:

AbstractColumn<M, I>

我有我的实现(IDataSource是一个接口):

SimpleColumn<I> extends AbstractColumn<IDataSource<I>, I>

问题开始于我应该将IDataSource<I>参数投射到其实施中,例如GenericDataSource<I>

SimpleColumn<I> column;
AbstractColumn<GenericDataSource<I>, <I>> newColumn = 
        (AbstractColumn<GenericDataSource<I>, <I>>)column;

我收到错误:

Type mismatch: cannot convert from AbstractColumn<GenericDataSource<I>,I> to AbstractColumn<IDataSource<I>,I>

如果我尝试将IDataSource对象(不是参数)转换为GenericDataSource,则没有错误:

IDataSource<T> ds;
GenericDataSource<T> gds = (GenericDataSource<T>)ds;

为什么java能够将IDataSource转换为GenericDataSource,但不能在通配符中执行相同操作?

1 个答案:

答案 0 :(得分:0)

泛型在最好的时候很棘手。首先,这里有两位代码。第一个(你的代码)不编译。第二个确实编译。不同之处在于AbstractColumn的类型参数。

    SimpleColumn<I> column = null;

    AbstractColumn<GenericDataSource<I>, I> newColumn1;
    newColumn1 = (AbstractColumn<GenericDataSource<I>, I>)column;

    AbstractColumn<IDataSource<I>, I> newColumn2;
    newColumn2 = (AbstractColumn<IDataSource<I>, I>)column;

通常我会通过放置&#34;来解决这个问题。扩展我&#34;或&#34;?超级我&#34;在其中一个类型参数中。但是,在这种情况下,这是行不通的。另请注意,AbstractColumn的第二个类型参数并不重要 - 删除它也不能解决问题。

    SimpleColumn<I> column = null;

    AbstractColumn<GenericDataSource<I>> newColumn1;
    newColumn1 = (AbstractColumn<GenericDataSource<I>>)column;

    AbstractColumn<IDataSource<I>> newColumn2;
    newColumn2 = (AbstractColumn<IDataSource<I>>)column;

我认为您遇到的问题与编译时类型擦除有关。基本上,在编译程序时,所有类型参数都转换为&#34; Object&#34;。编译器已经意识到在这种特殊情况下,它将无法执行正确的强制转换(并引发ClassCastException),因此阻止您执行此操作。我们可能需要Java Generics Guru来研究这个问题!