Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Gson TypeToken work?

I understand that in Java contrary to, for example, C# generics are compile-time feature and is removed via type erasure. So, how does Gson's TypeToken really work? How does it get the generic type of an object?

like image 464
Heisenberg Avatar asked May 02 '15 17:05

Heisenberg


People also ask

How does TypeToken work?

TypeToken uses an anonymous class to ensure it keeps generic type information, instead of just creating an object. Show activity on this post. Now you can easily get Type parameters to super type (TypeToken) as specified above.

What is TypeToken in GSON?

Class TypeToken<T> Represents a generic type T . Java doesn't yet provide a way to represent generic types, so this class does. Forces clients to create a subclass of this class which enables retrieval the type information even at runtime.


1 Answers

It's a trick!

From §4.6 of the JLS (emphasis mine):

Type erasure is a mapping from types (possibly including parameterized types and type variables) to types (that are never parameterized types or type variables). We write |T| for the erasure of type T. The erasure mapping is defined as follows:

The erasure of a parameterized type (§4.5) G is |G|.

The erasure of a nested type T.C is |T|.C.

The erasure of an array type T[] is |T|[].

The erasure of a type variable (§4.4) is the erasure of its leftmost bound.

The erasure of every other type is the type itself.

Therefore, if you declare a class with an anonymous subclass of itself, it keeps it's parameterized type; it's not erased. Therefore, consider the following code:

import java.lang.reflect.ParameterizedType; import java.util.Arrays; import java.util.HashMap;  public class Erasure<T> {     public static void main(String...strings) {       Class<?> foo = new Erasure<HashMap<Integer, String>>() {}.getClass();       ParameterizedType t = (ParameterizedType) foo.getGenericSuperclass();       System.out.println(t.getOwnerType());       System.out.println(t.getRawType());       System.out.println(Arrays.toString(t.getActualTypeArguments()));     } } 

This outputs:

null class Erasure [java.util.HashMap<java.lang.Integer, java.lang.String>] 

Notice that you would get a ClassCastException if you did not declare the class anonymously, because of erasure; the superclass would not be a parameterized type, it would be an Object.

like image 161
durron597 Avatar answered Sep 20 '22 07:09

durron597