Java Generics - illyfrancis/scribble GitHub Wiki

Covariant & Contravariant & Nonvariant (invariant)

Very well explained here

But in a nutshell, in Java

  • generics are invariant, e.g. List<String> and List<Object> are inconvertible
  • arrays are covariant, e.g. String[] is a subtype of Object[]

The Get and Put Principle

In the context of covariant and contravariant in generics, there a Get and Put principle that can be used to determine the use of covariant or contravariant.

Use an extends wildcard (covariant) when you only get values out of structure, use a super wildcard (contravariant) when you only put values into a structure, and don't use a wildcard when you both get and put.

Example

This principle at work in the signature of the copy method

public static <T> void copy(List<? super T> dest, List<? extends T> src)

Covariant return types

Since Java 5.

abstract class Shape {
  public Shape copy()
}

class Circle extends Shape {
  public Shape copy() { // returns a copy }
}

// then

Circle c1 = new Circle();
Circle c2 = c1.copy(); // -> compile error!
Circle c2 = (Circle)c1.copy();

// covariant return type
class Circle extends Shape {
  public Circle copy() { // returns a copy }
}

Circle c1 = new Circle();
Circle c2 = c1.copy(); // allowed
⚠️ **GitHub.com Fallback** ⚠️