Type Intersection in Java, or: Interest in Interfaces is Invaluable.
Tuesday, March 6th, 2007There was an interesting philosphical question posted in the comp.lang.java.programmer newsgroup the other day. Patricia, the original poster, had a question about using ArrayList as the declared type. She wanted to convey the fact that she wanted a List which has constant time random access methods, as this is an important property for her algorithm. Many of us live by the rule “Always use an interface, never a concrete type,” and she was questioning this. I personally think this dogma is a little to broad. However, it usually makes sense when using Java collections. As a matter of fact, you’ll find a lot of my code uses Collection instead of Set or List.
I guess Sun also thought it was important to convey constant time random access; they created an interface called RandomAccess just for that. RandomAccess is a marker interface for a List implementation to “indicate that they support fast (generally constant time) random access.”
Thats all well and good, but there’s a problem here.
RandomAccess myList = new ArrayList<Integer>(); // This compiles fine myList.get(0); // Whoops, compile error. RandomAccess doesn't extend List, so no get method;
Java 1.5 *almost* supports what we want… We want to say “Give me an object that is RandomAccess AND List<Integer>”. With the introduction of Generics, Java introduced Type Intersection. Unfortunately, they only introduced it in the context of Generics.
// Processes a RandomAccess List of integers, compiles fine
public <L extends RandomAccess&List<Integer> > void processList(L list) {
// ...
}
// Fails to compile.
public List<Integer> process(Collection<Integer> input) {
RandomAccess&List<Integer> output = new ArrayList<Integer>(input);
// ...
return output;
}
While this is too convoluted to answer Patricia’s philosophical question. It does bring us to an interesting, if incomplete, feature of Java.
