In Java, covariance allows the API designer to specify that an instance may be generalised as a certain type or any of that type's subtypes. For example:
List<? extends Shape> shapes = new ArrayList<Circle>();
// where type Circle extends Shape
Contravariance goes the other way. It allows us to specify that an instance may be generalised as a certain type or supertype.
List<? super Shape> shapes = new ArrayList<Geometry>();
// where Shape extends Geometry
How is Java generic's contravariance useful? When would you choose to use it?