0

For some historical reasons I must use an abstract class with a two wildcard parameters:

AbstractColumn<M, I>

And I have my implementation(IDataSource is an interface):

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

The problem starts when I should cast IDataSource<I> parameter to it's implementation, e.g. GenericDataSource<I>:

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

I'm getting an error:

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

And if I'm trying to convert IDataSource object(not parameter) to GenericDataSource, there is no errors:

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

Why java is able to convert IDataSource to GenericDataSource, but can't do the same in a wildcard?

  • 2
    The problem is that while `GenericDataSource` is a subclass of `IDataSource`, and thus can be cast, `AbstractColumn, >` is not a subclass, or superclass of `SimpleColumn`. – Jorn Vernee Aug 29 '16 at 10:00
  • 2
    Also a wildcard is a `?`, you seem to be talking about generic parameters. – Jorn Vernee Aug 29 '16 at 10:01
  • it seems there's no way out of this with the information you gave. Pheraps there are better ways to do this. May you post the full code of SimpleColumn and AbstactColumn? – Carlo Moretti Aug 29 '16 at 10:27
  • @JornVernee That makes sence. Is there any way to solve this problem? Because in this case I know, that for the column it's not important, what kind of implementation of `DataSource` is in use. I must specify this parameter just because of framework that I use. – Denis Dorohov Aug 29 '16 at 10:59
  • @Onheiron It was more an example then a real code, the real classes are huge and strong parametriezed(actually `AbstractColumn` has 3 generic parameters) – Denis Dorohov Aug 29 '16 at 11:04
  • 1
    It would be best to try and find a solution where you don't need to cast. I can't give you anything, the information is too limited. – Jorn Vernee Aug 29 '16 at 11:07
  • @JornVernee found the way without cast. Thanks for help. – Denis Dorohov Aug 29 '16 at 11:41

1 Answers1

0

Generics are tricky at the best of times. For a start, here are two bits of code. The first (your code) does not compile. The second does compile. The difference is in the type parameter to 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;

Normally I'd solve this problem by putting "? extends I" or "? super I" in one of the type parameters. However, in this case that is not working. Also note that the second type parameter to AbstractColumn doesn't matter - removing it does not resolve the problem either.

    SimpleColumn<I> column = null;

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

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

I think the problem you're hitting is related to compile-time type erasure. Basically, when the program is compiled all type parameters are converted to "Object". The compiler has realised that in this particular case, it will be unable to perform a correct cast (and raise a ClassCastException) so is blocking you from doing this. We probably need a Java Generics Guru to look into this!

Tim Wright
  • 109
  • 7