Consider the following Java class definitions:

```
class Animal {}
class Lion extends Animal {}

```

When defining a covariant `Cage` for `Animal`s I use this code in Java:

```
class Cage<T extends Animal> {
void add(T animal) { System.out.println("Adding animal..."); }
}

```

But the following Java example ...

```
public static void main(String... args) {
    Cage<? extends Animal> animals = null;
    Cage<Lion> lions = null;
    animals = lions;         // Works!
    animals.add(new Lion()); // Error!
}

```

... fails to compile with the following error:

> 
> *The method add(capture#2-of ? extends Animal) 
>  in the type Cage 
>  is not applicable to for the arguments (Lion)*
> 
> 
> 

Is this done because otherwise a different type like `Tiger` could be added after `animals = lions` and fail at runtime?

Could a special (hypothetical) rule be made that would not rejected it iff there would be only one sub-type of `Animal`?

(I know that I could replace `add`'s `T` with `Animal`.)
['https://Stackoverflow.com/questions/11760258', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/297776/']
When you *declare* your variable with this type: `Cage<? extends Animal>`; you're basically saying that your variable is a cage with some *unkown* class that inherits from `Animal`. It could be a `Tiger` or a `Whale`; so the compiler doesn't have enough information to let you add a `Lion` to it. To have what you want, you declare your variable either as a `Cage<Animal>` or a `Cage<Lion>`.
If so, that is likely a bug in the Scala compiler. Odersky et al. write in [An Overview of the Scala Programming Language](http://www.scala-lang.org/docu/files/ScalaOverview.pdf):

> 
> Scala’s type system ensures that variance annotations are
>  sound by keeping track of the positions where a type pa-
>  rameter is used. These positions are classied as covariant
>  for the types of immutable elds and method results, and
>  contravariant for method argument types and upper type
>  parameter bounds. Type arguments to a non-variant type
>  parameter are always in non-variant position. The position
>  ips between contra- and co-variant inside a type argument
>  that corresponds to a contravariant parameter. The type
>  system enforces that covariant (respectively, contravariant)
>  type parameters are only used in covariant (contravariant)
>  positions.
> 
> 
> 

Therefore, the covariant type parameter T must not appear as method argument, because that is a contravariant position.

A similar rule (with more special cases, none of which matter in this case) is also present in the the [Scala Language Specification (version 2.9)](http://www.scala-lang.org/docu/files/ScalaReference.pdf), section 4.5.