Monday, December 04, 2006

Super Type Tokens

Class<T> works fine so long as T is a raw type, but I recently needed to pass around references to full blown generic types. For example, due to the fact that Java uses erasure to maximize compatibility, List.class compiles but List<Integer>.class does not.

Ted recently ran into this problem, too. He was lucky enough to get off with a warning, but my code actually needs to differentiate between List<Integer> and List<String>.

Neal came to the rescue with a clever (and cleverly named) pattern for retaining otherwise non-reifiable types at runtime. Check out super type tokens.

In a nutshell, instead of saying List<Integer>.class, you can say new TypeReference<List<Integer>>() {}, where the API for TypeReference may look very similar to that of Class.

4 Comments:

Blogger Eugene Kuleshov said...

Yea, that Gafter's Gadget is definitely a brilliant idea! By the way, what for you are developing the dependency injection framework?

6:12 PM  
Anonymous Anonymous said...

Seems like a lot of reflection for little gain, why don't you do this instead:

interface Factory< T > { T newInstance(); }
...
Factory< List< String > > stringsFactory = new Factory< List< String > > {
public List< String > newInstance() { return new List< String >(); }
}

And on the naming front, what's wrong with Factory.

8:26 PM  
Blogger Bob said...

Eugene, just toying with some ideas. ;)

Anonymous, the newInstance() method was just a small example. Super type tokens go well beyond creating new instances of types.

The syntax may leave a little to be desired, but you can always add sugar. The semantics are what's important.

8:47 PM  
Anonymous Anonymous said...

You should just use Haskell (which is where Java generics came from in the first place), in which case you'd have different types for [Integer] (the equivalent of List<Integer>) and [String] (the equivalent of List<String>).

11:49 AM  

Post a Comment

<< Home