2015-05-02 14 views
14

Capisco che in Java contrariamente a, ad esempio, i generici C# sono funzionalità di compilazione e vengono rimossi tramite cancellazione di tipi. Quindi, come funziona G23's TypeToken? Come ottiene il tipo generico di un oggetto?Come funziona Gson TypeToken?

risposta

18

It's a trick!

From §4.6 of the JLS (sottolineatura mia):

Tipo cancellazione è una mappatura da tipi (possibilmente tra i tipi parametrici e digitare variabili) ai tipi (che non sono mai tipi parametrizzati o variabili di tipo). Scriviamo | T | per la cancellazione di tipo T. La mappatura della cancellazione è definita come segue:

La cancellazione di un tipo parametrizzato (§4.5) G è | G |.

La cancellazione di un tipo annidato T.C è | T | .C.

La cancellazione di un tipo di matrice T [] è | T | [].

La cancellazione di una variabile di tipo (§4.4) è la cancellazione del limite più a sinistra.

La cancellazione di ogni altro tipo è il tipo stesso.

Pertanto, se si dichiara una classe con una sottoclasse anonima di se stessa, mantiene il suo tipo parametrizzato; non è cancellato. Pertanto, si consideri il seguente codice:

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())); 
    } 
} 

Questo uscite:

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

noti che si otterrebbe un ClassCastException se non dichiarare la classe anonima, a causa della cancellazione; la superclasse non sarebbe un tipo parametrizzato, sarebbe un Object.

4

La cancellazione del tipo di Java si applica a singoli oggetti, non a classi o campi o metodi. TypeToken utilizza una classe anonima per garantire che mantenga informazioni di tipo generico, invece di creare semplicemente un oggetto.