Accessing generic types at runtime in Java

Arjan Blokzijl

I was writing my n-th Dao implementation, this time using JPA.
I (and probably a whole lot of others) usually create a DAO per entity, parameterizing the entity type.
Specific DAO instances for entities implement the generic DAO using their entity type as type parameter. One generic DAO implementation exists, containing common operations like findById, persist, remove, etc. This generic DAO uses the class type specified by the implementing DAO classes (e.g. a Person) to manipulate or query the entity specified by this type. The (slightly) annoying problem for me has always been to instantiate that entity type in the generic DAO superclass. I've always done this by just creating a constructor in the generic DAO which takes a class argument containing the required Class of the entity. However, there's a better way, which I'll show in this post.

To start with an example, the generic DAO interface looks like this:

public interface GenericEntityDao {

   T findById(Serializable id);

   List findAll();

   ... more methods omitted
}

And its generic DAO implementation class looks something like this:

public abstract class GenericJpaDao implements GenericDao {

  private Class entityBeanType;

  @PersistenceContext
  private EntityManager entityManager;

  public T findById(Serializable id) {
     return entityManager.find(getEntityBeanType(), id);
  }

  public List findAll() {
      return entityManager.createQuery("from " + getEntityBeanType().getName() )
                          .getResultList();
  }

  protected Class getEntityBeanType() {
      return entityBeanType;
  }
  ... more methods omitted
 
}

The question is, how do we obtain the parametized type of T for the entityBeanType field to use in our queries? Earlier, I used to just instantiate this type in the constructor, like so:

public GenericJpaDao(Class entityBeanType) {
     this.entityBeanType = entityBeanType;
}

public JpaPersonDao extends GenericJpaEntityDao implements PersonDao {
   public PersonDao() {
      super(Person.class);
   }
}

But this is a bit silly, since we already know from the type parameter that the entity we're interested in has type Person.
However, there is an easier way out: we can use Java's ParameterizedType class to obtain information about the declared generic type. As stated in the javadoc:

/**
* ParameterizedType represents a parameterized type such as
* Collection<String>.
*
* A parameterized type is created the first time it is needed by a
* reflective method, as specified in this package. When a
* parameterized type p is created, the generic type declaration that
* p instantiates is resolved, and all type arguments of p are created
* recursively.


Thus, it seems that ParameterizedType contains the information that we want. How do we obtain an instance of it? The answer lies in Java's getGenericSuperclass method, defined on the Class object. This returns a Type representing the superclass of this Class. The Javadoc of the method states the following:

* If the superclass is a parameterized type, the Type
* object returned must accurately reflect the actual type
* parameters used in the source code. The parameterized type
* representing the superclass is created if it had not been
* created before.



The Type interface itself is just a marker interface, containing no methods. Depending on the case at hand, an Type extending the Type interface will be returned. In our case, we'll use the getGenericSuperclass method on a class extending our GenericJpaDao class. Thus, the superclass is JpaGenericDao, which is a parameterized type. In this case, the actual the Type object returned by getGenericSuperClass will be a ParameterizedType instance. This class contains a method getActualTypeArguments, which returns an array containing all generic type parameters used in the source code.

This is precisely what we desire, so in our GenericJpaDao class constructor, can get rid of the Class argument, and instead do the following:

  @SuppressWarnings("unchecked")
  public GenericJpaDao() {
    this.entityBeanType = ((Class) ((ParameterizedType) getClass()
        .getGenericSuperclass()).getActualTypeArguments()[0]);
  }

We know there's precisely one type argument in our class, so we can take the first element of the array that is returned, which provides the Class of our entity. Thus we can get rid of all the annoying constructors with Class arguments, and handle determination of the entity type in just one place.

This may not provide the highest amount of code reduction you have ever experienced, but it's a neat trick in any case.

Comments (17)

  1. Maarten Winkels - Reply

    February 7, 2009 at 2:50 pm

    Hi Arjan,

    A neat trick indeed. I found it here, the first time I ever heard about it. The code itself though is just plain nasty, with all the explicit casting and using hardcoded array indexing. Also, it only works when you implement a generic interface or a generic superclass (I think?).

    Anyways, good to have it on the Xebia blog, so I know where to find that nasty line of code when I need it... ;)

    -Maarten

  2. Andrew Phillips - Reply

    March 5, 2009 at 12:33 pm

    A nice trick, indeed. But something to bear in mind here: this only works if

    • the type information is in a superclass and, thus,
    • the class that needs the type information inherits from the type-defining class.

    If you are class Foo<V> and you need access to the runtime type of V this unfortunately won't work. Neither if you are FooUtils and get passed an instance of Foo.

    I'll hopefully get round to writing a post about some of these issues soon...

  3. [...] by Andrew Phillips in the early afternoon: March 12, 2009 In a recent post, Arjan Blokzijl discussed how Class.getGenericSuperclass can be used to access generic type [...]

  4. [...] with the shared functionality and then subclass from that for each specific DAO. There are a lot of blogs out there about such a type-safe generic DAO pattern and you can even download some code from [...]

  5. Rob - Reply

    June 12, 2009 at 7:54 pm

    Thank you so much!! Saved me ours of javadoc reading :)

    I had the same feelings than you about redundancy by passing in the class. ParameterizedType is the solution!

  6. feng - Reply

    August 28, 2009 at 2:14 am

    Excellent article.

    I modified the code for the constructor as below so that it can handle multiple level inheritance.

    [edited to correct formatting]

    Class< ?> cls = getClass();
    while (!(cls.getSuperclass() == null 
        || cls.getSuperclass().equals(AbstractExpression.class))) {
      cls = cls.getSuperclass();
    }
    
    if (cls.getSuperclass() == null)
      throw new RuntimeException(”Unexpected exception occurred.”);
    
    this.entityBeanType = ((Class) ((ParameterizedType) 
      cls.getGenericSuperclass()).getActualTypeArguments()[0]);
    
  7. Luis Daniel Mesa Velásquez - Reply

    November 5, 2009 at 2:00 am

    Useful for when you have a subclass of a generic, in which case you don't really need it, cuz you know the generic type and it saves you, perhaps, 2 lines of code per subclass...

    completely useless if you don't have a subclass. I tried creating a "generic helper" to let me create a subclass and get around the block... It works, but i didn't like not having an elegant solution either.

  8. Jelmer - Reply

    February 5, 2010 at 11:08 am

    Yes this is a useful trick. The exact same piece of code has been part of the caveat emptor sample applicatication for the Java Persistence with Hibernate for quite some time. As has been pointed out in the comments. This code doesn't work in all cases.

    If you use spring3 you could use

    this.entityBeanType = GenericTypeResolver.resolveTypeArgument(getClass(), GenericDao.class)

    as a more elegant and robust solution

  9. [...] Tohle je tak trošku předskokan prvně uvedeného článku – s tímhle bych doporučoval zač... [...]

  10. Thomas - Reply

    September 8, 2010 at 10:22 am

    Good read indeed.

    For those who are interested, here's an extension:

    We're using a similar approach with our DAOs having more than one type parameter due to our architecture.

    Additionally, we have a hierarchy of abstract generic DAOs, so there's the problem of getting information on the actual parameter types for the most basic DAOs.

    Consider the following:

    [edited to correct formatting] ProjectSpecificUserDAO -> AbstractUserDAO<OtherParameter, UserEntity> -> AbstractBaseDAO<UserEntity>

    When reading the actual type of UserEntity in AbstractBaseDAO you'll get into trouble since when using the first actual type parameter you'd get the class for OtherParameter instead of UserEntity.

    Additionally, Java reflection doesn't make it easy to go down and get the actual parameter for AbstractBaseDAO, since all you get easily in that case is the name 'UserEntity'.

    However, here's a solution that we're using now: http://www.artima.com/weblogs/viewpost.jsp?thread=208860

  11. Andrew Phillips - Reply

    September 10, 2010 at 8:25 am

    @Thomas: Looks like what you've come up with is very similar to what is discussed in this post. Might be interesting for you to have a look!

  12. [...] http://blog.xebia.com/2009/02/07/acessing-generic-types-at-runtime-in-java/ Share this:TwitterFacebookLike this:LikeBe the first to like this. [...]

  13. Varun Nagpal - Reply

    August 31, 2012 at 7:49 am

    Thanks for the code snippet.

    I had a suspicion that this could be done but never actually got to find out the correct reflection API.

    Thanks again.

  14. Mohamed Ennahdi El Idrissi - Reply

    August 28, 2013 at 3:12 pm

    http://www.scribd.com/doc/163398138/Java-Reflection-with-Generics-Practical-Case

  15. Sean - Reply

    March 14, 2014 at 9:12 am

    Curious if anyone has tested the performance of this. Specifically the reflection part to get the type.

  16. mJr - Reply

    April 3, 2014 at 3:45 pm

    A really neat trick. I tried for hours to get past that passing-the-type-as-an-argument silliness.

    Thank you. :)

Add a Comment