It's not a duplicate question because I specifically ask how does the compiler allow to add a Cat to a List<? super Cat> catList collection which ALREADY contains a Dog.You see animaList already contains Cats and Dogs because they're Animals but calling addCat which takes a List<? super Cat> allows adding a new Cat i.e. add(new RedCat()); despite that the list already contains a Dog. Shouldn't the compiler disallow this in order to fulfil the List<? super Cat>signature in that it tries to add Cats to a list already containing Dogs?
However explicitly calling
catList.add(new Dog());
enforces the constraint.So the question is why the difference in behaviour?
Original question:
I've been playing with Java generics and noticed a strange(?) issue.
In the following code snippet you can add both a Dog and Cat into the animalList and then pass this list into addCat(List<? super Cat> catList)
and add another Cat instance.So we have a List with both Dogs and Cats which overides the ? super Cat boundary, in that it should not allow Dogs?
However as soon as you uncomment the
//catList.add(new Dog());
line, you get a compile time error
(argument mismatch; Dog cannot be converted to CAP#1)
What's going on here? The code is amended from this tutorial
 package com.tutorialspoint;
    import java.util.ArrayList;
    import java.util.List;
    public class GenericsTester {
       public static void addCat(List<? super Cat> catList) {
         catList.add(new RedCat());
         catList.add(new Cat());
         //catList.add(new Dog());
          System.out.println("Cat Added");
       }
       public static void main(String[] args) {
          List<Animal> animalList= new ArrayList<Animal>();
          List<Cat> catList= new ArrayList<Cat>();
          List<RedCat> redCatList= new ArrayList<RedCat>();
          List<Dog> dogList= new ArrayList<Dog>();
          animalList.add(new Dog());
          animalList.add(new Cat());
          animalList.add(new RedCat());
          addCat(animalList);
            System.out.println("all ok");
       }
    }
    class Animal {}
    class Cat extends Animal {}
    class RedCat extends Cat {}
    class Dog extends Animal {}
 
     
    