Showing posts with label iterators. Show all posts
Showing posts with label iterators. Show all posts

Sunday, November 04, 2007

Java 5+ Iterator Adapters

I've been working with Java Generics more lately, and have run smack into the "Wall of Erasure". I'm referring to the fact that generics disappear in the bytecode. As you probably know, generics were a targeted feature at a time when Sun was attempting to avoid changing the Java Virtual Machine (JVM). They really wanted to maintain backward compatibility. So, this compromise was put forth to maintain backward compatibility. In a classic case of irony, other changes forced a change the JVM in the same release that gave us generices, but the compromised version of generics stayed. So we are stuck with half an implementation of generics.

Recently, I've been doing work with interfaces and extending interfaces, as in:

public interface Superclass {
// ...
}

public interface Subclass extends Superclass {
// ...
}

I have classes which implement a third interface:

public interface DoesStuff {
Iterator<Superclass> iterator();
// ...
}


You would think that an implementation of DoesStuff could return an Iterator for the iterator method:

public class MyClass implements DoesStuff {
// ...
private Set<Subclass> myThings = new HashSet<Subclass>();
// ...
public Iterator<Superclass> iterator() {
return myThings.iterator();
}
// ...
}

Unfortunately, the Wall of Erasure means we can't do this. Try it for yourself if you don't believe me.


So, what to do? Happily, there is a simple answer. We create an adapter that adapts the subclass iterator to the superclass iterator:


/**
* Adapts a derived class iterator to a base class.
*/
public class IteratorAdapter<B, D extends B> implements Iterator<B> {
private Iterator<D> d;

public IteratorAdapter(Iterator<D> aD) {
d = aD;
}

public boolean hasNext() {
return d.hasNext();
}

public B next() {
return d.next();
}

public void remove() {
d.remove();
}
}

The sad thing is that this shouldn't be necessary. It's trivial. It shouldn't have to be written by developers. The simplicity of this is a clear sign that we need to tear down the Wall of Erasure.

Will it happen any time soon? I hope so. Though I'm hearing talk that "erasing erasure" is probably off the table for Java 7. That would be a truly sad thing.