javagenericsvariancecontravariance

How to use Contravariance in Java with Classes


I am learning Java variance.

I am getting the Covariant to work but not Contravariance where I can accept a super type.

I have a simple class hierarchy for this:

Animal, Cat, Lion

Then I have two classes as Generic holders:

CovariantAnimalHolder ContraVariantHolder

The Covariant works fine but Contravariance isnt working.

Here is the code:

public class Animal {
    private String name;

    public Animal(String name) {
        this.name = name;
    }

    public Animal() {

    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}


public class Cat extends Animal {
    private boolean isWild;

    public Cat(boolean isWild) {
        this.isWild = isWild;
    }

    public Cat(){

    }

    public boolean isWild() {
        return isWild;
    }

    public void setWild(boolean wild) {
        isWild = wild;
    }
}

public class Lion extends Cat{

    private boolean isExtinct;

    public Lion (boolean isExtinct) {
        this.isExtinct = isExtinct;
    }

    public Lion () {

    }

    public boolean isExtinct() {
        return isExtinct;
    }

    public void setExtinct(boolean extinct) {
        isExtinct = extinct;
    }
}

Animal Holders:

public class CovariantAnimalHolder<T extends Cat> {
    private T animalHolder;

    public T getAnimalHolder() {
        return animalHolder;
    }

    public void setAnimalHolder(T animalHolder) {
        this.animalHolder = animalHolder;
    }
}

Main program:

So far great

public class VarianceMain {

    public static void main(String[] args) {
        //This works
        CovariantAnimalHolder<Lion> lionCovariantAnimalHolder = new CovariantAnimalHolder<Lion>();

        //This works:
        CovariantAnimalHolder<Cat> catCovariantAnimalHolder = new CovariantAnimalHolder<>();

        //This should not work, Perfect!
        //CovariantAnimalHolder<Animal> animalCovariantAnimalHolder = new CovariantAnimalHolder<Animal>();
    }
}

But when I create the ContraVariant holder I am getting some basic errors which I can't understand:

public class ContravariantAnimalHolder<T super Cat>{
    private T animalHolder;
}

Error:

enter image description here


Solution

  • In Java, you cannot define a generic type as a covariant or contravariant, as you can in other languages, for example, in scala

    Instead, in java, what you define are generic types with Upper bounds which limit you to the use of extends when it comes to types, and you cannot use super with generic types, reason you cannot use it in your ContravariantAnimalHolder class.

    You can, however define methods with lower bounded wildcards, which, depending on what you need may fit your needs for contravariant