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.