Java 5 Type Erasure is frustrating. I'm coding along, enjoying the glorious type safety of generics. And then I try to do a little more with the T
s, and erasure shows up, "You can't do that!" I can't test an object if it really is a T
. I can't inspect T.class
using reflection. And I certainly can't new up a T
. Yuck.
We're in a unique situation with Guice. Its type literals and injection points have complete generic information. It can follow long chains of type variables throughout an object model. In my app, I've got a Robot<T>
that injects a Claw<T>
. When I request a Robot<Adamantium>
, Guice knows to find an adamantium claw.
And now, this type information is available to application code. I can write a Claw<T>
class that actually knows what T
is at runtime!
Consider GuardingList<T>
, which enforces type safety at runtime:
class GuardingList<T> extends AbstractList<T> {
private final TypeLiteral<T> elementType;
private final ArrayList<T> delegate = new ArrayList<T>();
@Inject
GuardingList(TypeLiteral<T> elementType) {
this.elementType = elementType;
}
public boolean add(T t) {
checkArgument(elementType.getRawType().isInstance(t),
"Cannot add %s which is not of type %s", t, elementType);
return delegate.add(t);
}
public T get(int i) {
return delegate.get(i);
}
public int size() {
return delegate.size();
}
}
When injected, Guice applies its type knowledge to inject the correct TypeLiteral<T>
. The GuardingList
blows up when I add an invalid element:
public static void main(String[] args) {
Injector injector = Guice.createInjector();
List<String> listOfString = injector.getInstance(
new Key<GuardingList<String>>() {});
listOfString.add("A");
listOfString.add("B");
/* totally unsafe, but this compiles and runs */
List<Object> rawList = (List) listOfString;
/* throws an IllegalArgumentException, since the GuardingList
knows that its elements must be Strings */
rawList.add(666);
}
Types are the natural currency of Java. Erasure is frustrating 'cause it takes them away from you at runtime. And now Guice can give 'em back.