Subclassing and Java Generics, revisited

Posted on November 3, 2010 by Tommy McGuire

Map<String, Map<String,String>> map = new HashMap<String, HashMap<String,String>>() ;



Map<String, ? extends Map<String,String>> map = new HashMap<String, HashMap<String,String>>();

map. put("one", new HashMap<String, String>()) ;



Map<String, Map<String,String>> map = new HashMap<String, Map<String,String>>();

map.put("one", new HashMap<String, String>());



Class structure

public class A { }

public class B extends A { }

public class C extends A { }



List<B> can be used as a subtype of List<A> (or List<B> <: List<A>), which is described as a covariant use,

use, List<A> can be used as a subtype of List<B> (or List<A> <: List<B>), which is described as a contravariant use, or

use, or List<A> and List<B> can be entirely unrelated and cannot be interchanged, which is described as invariant.

Covariant Contravariant Extraction public A covExtInner(List<? extends A> as) {

return as.get(0);

}



public void covariantExtraction() {

List<B> bs = new ArrayList<B>();

bs.add(new B());



A a = covExtInner(bs);

} public B conExtInner(List<? super B> bs) {

return bs.get(0) ;

}



public void contravariantExtraction() {

List<A> as = new ArrayList<A>();

as.add(new A());



B b = conExtInner(as);

} Insertion public void covInsInner(List<? extends A> as, A a) {

as. add(a) ;

}



public void covariantInsertion() {

List<B> bs = new ArrayList<B>();

A a = new A();



covInsInner(bs, a);

} public void conInsInner(List<? super B> bs, B b) {

bs.add(b);

}



public void contravariantInsertion() {

List<A> as = new ArrayList<A>();

B b = new B();



conInsInner(as, b);

}

Valid operations

Covariant extraction

Contravariant insertion

Invalid operations

Covariant insertion

Contravariant extraction

The bottom line

The Get and Put Principle: use an extends wildcard when you only get values out of a structure, use a super wildcard when you only put values into a structure, and don't use a wildcard when you both get and put.

Please enable JavaScript to view the comments powered by Disqus.