Monday, November 4, 2013

A handy hack for getting around Java type erasure

Once a Java class is compiled, any generic information is lost. Meaning that an ArrayList of Cars at runtime becomes an ArrayList and the fact that it stores Cars is lost.

There is a way around it, if you have access to the class or object that contains that ArrayList.

Lets take a simple domain object that contains a list : 
public class Domain {

 private List myList = new ArrayList();

 // Access methods removed
 
}
This class contains the list we want to inspect, the maguffin we're searching for. If we run that class through this inspector :
public class TypeInspector {

 public void inspect(Class clazz) {
  for(Field field : clazz.getDeclaredFields()) {
   if(isCollection(field)) {
    inspectType(field);
   } 
  }
 }
 
 private void inspectType(Field field) {
  String rawType = field.getGenericType().toString();
         rawType = rawType.substring(rawType.indexOf('<') + 1);
         rawType = rawType.substring(0, rawType.length() - 1);
           
         try {
   System.out.println(Class.forName(rawType));
  } catch (ClassNotFoundException e) {
   System.out.println("Couldnt find "+ rawType);
  }
 }

 private boolean isCollection(Field field) {
  return Collection.class.isAssignableFrom(field.getType());
 }
}

This inspector can retrieve the generic type from the field in the class that contains it. Parse the String description of the generic type to remove the ArrayList details which will give us our Maguffin.

1 comment:

Curious Bystander said...

Huh?? What's wrong with:

if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;

/// stuff hiree
}