PUBLIC OBJECT

Guice punches erasure in the face!

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 Ts, 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.

Reify today.