1

I have following sample that cannot compile and produces Error:() java: type argument GroupOfPartsDecorImpl<V> is not within bounds of type-variable GOP. Code is the following:

class MainContainerGroupPartDecorator<V, GOP extends GroupOfParts<V, PartDecorator<V, ? extends Part<V>>>> 
extends BaseContainerGroupPartDecorator<V, GOP> {
    public static <V> MainContainerGroupPartDecorator<V, GroupOfPartsDecorImpl<V>> getInstance() {
        return null;
    }
}

class BaseContainerGroupPartDecorator<V, GOP extends GroupOfParts<V, ?>> {
    void something() {}
}

class GroupOfPartsDecorImpl<V> implements GroupOfParts<V, PartDecorator<V, PartImpl1<V>>> {
    @Override
    public Collection<PartDecorator<V, PartImpl1<V>>> getParts() {
        return null;
    }
}

interface GroupOfParts<V, P extends Part<V>> {
    Collection<P> getParts();
}

class PartDecorator<V, P extends Part<V>> implements Part<V> {
    @Override
    public V getId() {
        return null;
    }
}

class PartImpl1<V> implements Part<V> {
    @Override
    public V getId() {
        return null;
    }
}

Since GOP is GOP extends GroupOfParts<V, PartDecorator<V, ? extends Part<V>>> and GroupOfPartsDecorImpl should be in the end GroupOfParts<V, PartDecorator<V, Part<V>> why this error shows up?

Bojan Vukasovic
  • 2,054
  • 22
  • 43

2 Answers2

2

The second generic parameter to GroupOfParts must be PartDecorator<V, ? extends Part<V>>. And since generics are invariant by default there can be no deviation from this. But GroupOfPartsDecorImpl uses PartDecorator<V, PartImpl1<V>>, which is not the same, so it doesn't compile.

You can solve this by making the second parameter covariant in the declaration of MainContainerGroupPartDecorator:

class MainContainerGroupPartDecorator<V, GOP extends GroupOfParts<V,
    ? extends PartDecorator<V, ? extends Part<V>>>> 
    extends BaseContainerGroupPartDecorator<V, GOP> {

(Basically changing PartDecorator<V, ? extends Part<V>> to ? extends PartDecorator<V, ? extends Part<V>>)

Jorn Vernee
  • 31,735
  • 4
  • 76
  • 93
  • could you please explain this? _And since generics are invariant by default there can be no deviation from this_ – senseiwu May 22 '17 at 08:38
  • 1
    @zencv I'd refer to this question: http://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-arent-javas-generics-implicitly-p – Jorn Vernee May 22 '17 at 08:39
  • This seems like solving the problem. Thanks. – Bojan Vukasovic May 22 '17 at 10:25
  • @JornVernee one unrelated question: is it possible to have this kind of specification class `SubMainContainerGroupPartDecorator> extends BaseContainerGroupPartDecorator>> {` -> so instead to specify GroupOfParts<> I specify Part? – Bojan Vukasovic May 22 '17 at 10:38
  • @bojanv55 No, a super type can not use any wildcards. – Jorn Vernee May 22 '17 at 13:12
1

The problem is your bounded wildcard in the 3rd level of your 2nd generic ? extends Part<V>. You may specify it by an additional generic P

class MainContainerGroupPartDecorator<V, P extends Part<V>, GOP extends GroupOfParts<V, PartDecorator<V, P>>>
    extends BaseContainerGroupPartDecorator<V, GOP>
{
    public static <V> MainContainerGroupPartDecorator<V,PartImpl1<V>, GroupOfPartsDecorImpl<V>> getInstance() {
        return null;
    }
}
Stefan Warminski
  • 1,845
  • 1
  • 9
  • 18