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