Wednesday, March 18, 2009

Super type tokens

Now I read quite a bit of Java code but I always make an effort to understand each bit of code that passes by my desk and I do still get some surprises. Whilst looking at some jersey client code I noticed the following line.

 public List<StatusBean> getFriendsTimelineJson() {
           return wr.path("statuses/friends_timeline.json")
                   .header(AUTHENTICATION_HEADER, authentication)
                   .accept(MediaType.APPLICATION_JSON_TYPE)
                   .get(new GenericType<List<StatusBean>>() {
           });
 }

Note the final parameter in the builder that take a instance of "GenericTypeList" which appears to be some kind of anonymous type. It turns out to be a clever workaround for generic type erasure.

Consider the following method:

public <T> T getFavorite(Class<T> klass) {
    return ...;
}

Type erasure means the following won't compile:

   List<String> list = thing.getFavourite(List<String>.class);

Using a "super type token" solve this problem as generic types are not erased from class definitions, so you can write:

   List<String> list = thing.getFavourite(
       new GenericType<List<String>>() {});

With the following implementation of the getFavourite method: (See GenericType.java)

public <T> T getFavorite(GenericType<T> klass) {
    return getFavourite(klass.getRawClass());
}

You can also see this used in fest-reflect API for the same reasons. (TypeRef in the FEST API example)

2 comments:

jambay said...

Templates have always made my head hurt since C++ at University. Thanks for giving me a headache :).

Gerard Davison said...

My pleasure, :-)

Gerard