Please explain why {}
used in
Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
This is from Gson documentation link to documentation
It's creating a new anonymous type. This is a workaround for type erasure, because you can get the Collection<Integer>
reflectively via Class.getGenericSuperclass()
and Class.getGenericInterfaces()
if the class is not generic (*).
This code basically implements the same functionality Ideone demo:
abstract class TypeToken<T> {
Type getType() {
ParameterizedType t = (ParameterizedType) getClass().getGenericSuperclass();
return t.getActualTypeArguments()[0];
}
}
public static void main (String[] args) {
Collection<Integer> list = new ArrayList<>();
System.out.println(list.getClass().getGenericInterfaces()[0]);
TypeToken<Collection<Integer>> tt = new TypeToken<Collection<Integer>>() {};
System.out.println(tt.getClass().getGenericSuperclass());
System.out.println(tt.getType());
}
Output:
java.util.List<E>
Ideone.Ideone$TypeToken<java.util.Collection<java.lang.Integer>>
java.util.Collection<java.lang.Integer>
You can see that the "Integer"-ness of the Collection
is lost; but it's still present in the TypeToken
, so you can get it via the getType()
method.
(*) An important point here is that you can't (correctly) create a TypeToken
in a generic method. For example:
<T> TypeToken<T> getGenericToken() {
return new TypeToken<T>() {};
}
won't work like you might expect Ideone demo.
TypeToken<Collection<String>> t = getGenericToken();
System.out.println(t.getType()); // T, not Collection<String>.