Monday, November 12, 2007

The Wall of Erasure

I mentioned the term "Wall of Erasure" in my previous post about Iterator adapters. My friend Weiqi Gao described it best in his blog entry where he said 'Every really cool idea involving Java generics will invariably lead to insurmountable difficulties the root cause of which is erasure'.

I just got a chance to read Eric Burke's latest blog entries, and he too has hit the Wall of Erasure (some commentors are suggesting it's not "all" erasure's fault, but that's a red herring).

Monday, November 05, 2007

Unit Testing Simple Code

I just read Alex Miller's blog entry where he states quite nicely why unit testing even very simple code is not dumb. He posted because of Eric Burke's excellent discussion of the matter.

I really don't have much more to add, except to add one more voice to those who state that unit testing seemingly trivial code is important. I will say that I've actually caught silly mistakes (like failing to set a field to the correct value in a constructor) with simple unit tests. Also, writing tests for such code lets me spend more time thinking about the hard parts of the problem and less time examining 'simple' code to make sure it is correct.

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.