This is an oversimplified version of the compiler behaviour I'm trying to understand:
class Scratch {
public static void main(String[] args) {
HouseCat<? extends Mammal> hcat = new Tabby();
//HouseCat<Mammal> won't work, compiler catches incorrect type parameter bound
HouseCat<CrazyHouseCat> crazyCat = new Tabby();
}
}
interface Mammal<T extends Mammal> extends Comparable<T>{
T cloneInstance();
}
interface Feline<T extends Feline> extends Mammal<T>{}
interface HouseCat <T extends HouseCat> extends Feline<T>{}
interface CrazyHouseCat<T extends CrazyHouseCat> extends HouseCat<T>{
void pushStuffOverTvStand();
}
class Tabby implements CrazyHouseCat<CrazyHouseCat>{
@Override
public CrazyHouseCat cloneInstance() {
return null;
}
@Override
public void pushStuffOverTvStand() {
}
@Override
public int compareTo(CrazyHouseCat o) {
return 0;
}
}
In the snippet above, HouseCat<? extends Mammal> is a reference with a wider range of types than that is allowed by the HouseCat interface, namely: HouseCat<T extends HouseCat>
If I were to try to do something like HouseCat<Long> the compiler would tell me that Long does not satisfy the type parameter's constraints. Well, so does not <? extends Mammal>, at least potentially.
The compiler would not let me create an instance that violates the type parameter T's constraints but I'm confused about its behaviour regarding the use of Mammal as the upper bound of the reference. There is an invalid type range between (HouseCat,Mammal] so why won't the compiler refuse this reference definition?
Clarification:
My question is not about the meaning of wildcard ?. I'm asking why the compiler is allowing a reference to a parameterised type instance be defined using a wider range of types than what is allowed by the parameterised type's definition. The mentioned questions do not address this specific case, they're about the meaning of a wildcard. My question is about the valid range of the wildcard, which the compiler does not seem be enforcing.