Saturday, July 2, 2011

Finding parameterized type at runtime

Say, I have a base class ParametrizeTest and a subclass of it SubClass. You can easily find runtime class of T for SubClass as following :

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class ParametrizeTest<T> {
 public void getType() {
  ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
  Type ts[] = type.getActualTypeArguments();
  Class c = (Class) ts[0];
  System.out.println(c.getName());  
 }
}

public class SubClass extends ParametrizeTest<String> {
 public static void main(String args[]) {
  new SubClass().getType();
 }
}


You can do a valid typecast, only if you have written a class which extends some class. Otherwise, have you wondered whether this will work :

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;


public class ParametrizeTest<T> {
 public void getType() {
  ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
  Type ts[] = type.getActualTypeArguments();
  Class c = (Class) ts[0];
  System.out.println(c.getName());  
 }
 
 public static void main(String args[]) {
  ParametrizeTest<String> p = new ParametrizeTest<String>();
  p.getType();
 }
}


You will notice that it throws a "java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType"

So, how can you find it ?

A simple hack which I came across was to add a curly braces in the end while instantiation. This essentially create a anonymous subclass of ParametrizeTest.

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;


public class ParametrizeTest<T> {
 public void getType() {
  ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
  Type ts[] = type.getActualTypeArguments();
  Class c = (Class) ts[0];
  System.out.println(c.getName());  
 }
 
 public static void main(String args[]) {
  ParametrizeTest<String> p = new ParametrizeTest<String>(){};
  p.getType();
 }
}


But, overall its not a good idea. Actually, due to erasure, type information is removed after compilation. So, there is no way to get class of parametrized type at runtime. This is not even mentioned in roadmap of JDK 1.7. Hope that its available in JDK 1.8 :)

1 comment:

  1. I want to use it within webservice and I cannot use curly brace so I get cast error. How can I use it without curly brace?

    ReplyDelete