I have a method with the following signature:
// Converts a json string to a list of objects
// Assumption: json is an array, and all items in the list are of the same type
public <T> List<T> getListFromJson( String json, Class<T> itemType, List<T> defValue ) {
final ArrayList<T> list = new ArrayList<T>();
for( JsonElement e : parser.parse(json).getAsJsonArray())
list.add( (T) (
Number.class.isAssignableFrom(itemType) ? e.getAsNumber() :
Boolean.class.isAssignableFrom(itemType) ? e.getAsBoolean() :
Character.class.isAssignableFrom(itemType) ? e.getAsCharacter() :
String.class.isAssignableFrom(itemType) ? e.getAsString() :
JsonElement.class.isAssignableFrom(itemType) ? e :
null
)
);
return list;
}
It reads the json string and converts it to a list of the appropriate type of object, eg. Integer, String, etc.
Is there a robust way to remove the Class<T> argument from the method by inferring it from the List<T> parameter? Eg. Is there a way I can change the method signature to the following without losing functionality?
public <T> List<T> getListFromJson( String json, List<T> defValue ) {
...
}
It seems like the solution is going to require some fancy manipulation of ParameterizedType. I’ve looked at the following, but either I’m using these methods incorrectly or they’re not doing what I expect:
- getTypeArguments() from http://www.artima.com/weblogs/viewpost.jsp?thread=208860
- getActualTypeArguments() from https://code.google.com/p/aphillips/source/browse/commons-lang/trunk/src/main/java/com/qrmedia/commons/lang/ClassUtils.java
Due to type erasure, you definitely can’t “infer” what
Tis–it doesn’t even exist at runtime. The closest you could come is inspect the values indefValue(if it has values) and get the class of the elements there.Edit
With regards to your thinking of using reflection like
getTypeArguments(), etc. Those only provide data for declared types, never actual types. So for example, if you got a handle to theMethodobject and calledgetTypeParameters(), you’d just get an array containing a type object representingT–not the actual type thatTrepresents at some specific runtime invocation.