Skip to content


Finding Generic Type Parameters with Guava

Over the last year, I’ve ran into a number of cases where refactoring led to a generic abstract base class that accepted its parameter type class in its constructor. Something like this-

public abstract class BaseClass<T> {
    private final Class<T> type;
    protected BaseClass(Class<T> type) {
        this.type = type;
    }
}
 
public class ConcreteClass extends BaseClass<String> {
    public ConcreteClass() {
        super(String.class);
    }
}

Note the duplication of the type in the generic parameter declaration and in the call to the superclass constructor. Sadly, this is the usual workaround pattern.

Until Guava, finding the parameter type of a generic wasn’t easy because of type erasure at runtime it required a decent chunk of reflection code and loops to walk the class hierarchy. (Yes, TypeTools etc have similar functionality, but I prefer a minimal set of dependencies and already use Guava everywhere.) With Guava, this becomes an easy two lines of code:

public abstract class BaseClass<T> {
  private final TypeToken typeToken = new TypeToken(getClass()) { };
  private final Type type = typeToken.getType(); // or getRawType() to return Class<? super T>
}

No duplication, no constructor args — much simpler!

Example 1 – AbstractInjectableProvider for RESTful services with Jersey

This code has gone through a few revisions. It originally passed the Type in the constructor, as outlined above and in this Injection Providers article. Then I decided to be clever and use reflection to get the Super Type Tokens. Except, because the actual type parameter can be anywhere in the hierarchy, you have to traverse all the subclasses like so

As you can see, this is quite complex and messy. Simplify it using Guava.

Example 2 – AbstractXmlReader for RESTful web services with Jersey

I suspect anybody using Jersey could use something like this.

Wooiee! What else can you simplify using Guava to get parameterized Type Tokens?

Posted in Tutorials.


2 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Ninja says

    public abstract class BaseClass {
    private final TypeToken typeToken = new TypeToken(getClass()) { };
    private final Type type = typeToken.getType(); // or getRawType() to return Class
    }

    Can you replace that with this?
    public abstract class BaseClass {
    private final TypeToken typeToken = new TypeToken(getClass()) { };
    private final Type type = typeToken.getType(); // or getRawType() to return Class
    }

    • codyaray says

      I’m not seeing a difference in the two. Did my dumb comment box lose some formatting somewhere or something?



Some HTML is OK

or, reply to this post via trackback.

 



Log in here!