0

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.

mahonya
  • 9,247
  • 7
  • 39
  • 68
  • 1
    I'm not sure what you're trying to do, but there are many raw types in the code you posted, which is not a good idea. – Eran Aug 06 '19 at 11:59
  • Possible duplicate of [in Java syntax, Class extends Something>](https://stackoverflow.com/questions/8422842/in-java-syntax-class-extends-something) – Sharon Ben Asher Aug 06 '19 at 12:15
  • @SharonBenAsher I don't think so. Please see my clarification. – mahonya Aug 06 '19 at 13:28
  • ` //HouseCat won't work, compiler catches incorrect type parameter bound` - because Mammal doesn't extend Mammal – ACV Aug 06 '19 at 13:36
  • @ACV no it won't work because Mammal is a super type of the allowed type for HouseCat's type parameter (HouseCat again). Types that extend themselves are valid type parameters in Java generics – mahonya Aug 06 '19 at 13:52
  • You're right it's >= – ACV Aug 06 '19 at 14:53

1 Answers1

0

This looks like it answers your question. Basically HouseCat<? extends Mammal> allows to create a HouseCat<[insert type that extends Mammal here]>. All <? extends Mammal> does is act as a generic. In your example I don't see why you'd try to do it this way, but I hope this helps.

NightDice
  • 116
  • 7