Java Generics - illyfrancis/scribble GitHub Wiki
Very well explained here
But in a nutshell, in Java
- generics are invariant, e.g.
List<String>andList<Object>are inconvertible - arrays are covariant, e.g.
String[]is a subtype ofObject[]
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
extendswildcard (covariant) when you only get values out of structure, use asuperwildcard (contravariant) when you only put values into a structure, and don't use a wildcard when you both get and put.
This principle at work in the signature of the copy method
public static <T> void copy(List<? super T> dest, List<? extends T> src)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