Search code examples
javainitializationjson-deserialization

Why {} is used in this statement for instantiation, Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();


Please explain why {} used in

Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();

This is from Gson documentation link to documentation


Solution

  • 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>.