2013-03-18 3 views
12

Quando uso GSON per analizzare tra oggetto e JSON, l'inizializzazione di un TypeToken è così strano:perché la costruzione di TypeToken in Gson è così strana?

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

So solo questo tipo di formato: new TypeToken<Collection<Integer>>().getType();, ciò che è le parentesi graffe in precedenza per? Grazie in anticipo!

P.S. Ho esaminato il codice sorgente della classe TypeToken, è un class (non di interfaccia o astratto) e senza alcun costruttore, il che significa che utilizza no-parameter constructor come predefinito.

P.S.2 Quando elimino le parentesi, indica che il costruttore non è visibile. Quando ho guardato all'interno della classe TypeToken, questo è il costruttore:

protected TypeToken() { 
     this.type = getSuperclassTypeParameter(getClass()); 
     this.rawType = (Class<? super T>) $Gson$Types.getRawType(type); 
     this.hashCode = type.hashCode(); 
    } 

Perché non basta usare public invece?

risposta

18

"Weird" non è esattamente un termine tecnico. La classe è definita in modo tale da costringerti a specificare esplicitamente un parametro generico da associare a una sua istanza concreta. Poiché le classi Java compilate conservano le informazioni sui loro parametri generici, tali informazioni diventano quindi disponibili per le librerie framework che lo richiedono.

Questo è lo scopo di un token di tipo super.

+1

Grazie, un'altra domanda: cosa succede se si cambia il costruttore predefinito da 'protected' a' public', quando si inizializza 'TypeToken', dobbiamo ancora specificare il generico a' Collection ', perché l'istanza TypeToken non può essere a conoscenza di il tipo di collezione in questo senario? – Judking

+4

Beh, in effetti, avere la protezione del costruttore è essenziale.Impedisce alle persone di essere in grado di fare 'TypeToken t = new TypeToken ();', che vanificherebbe l'intero scopo della classe. Così com'è, sei * forzato * a sottoclasse in realtà per definire completamente il token, che è ciò che i progettisti intendono. Si può pensare a tutto ciò come a un trucco per aggirare il fatto che Java implementa i generici tramite la cancellazione dei tipi. Spero che renda le cose più chiare. – Perception

+1

Quindi, questo è il punto: Se uso 'TypeToken t = new TypeToken ();', secondo il meccanismo dei generics, non posso ottenere alcun tipo di informazione su 'Whatever'; mentre se sottoclassi il TypeToken usando 'TypeToken t = new TypeToken () {};', posso ottenere le informazioni sul tipo 'Whatever'? Ho ragione? – Judking

1

TypeToken è astratto, quindi devi creare una classe concreta per istanziarlo, ecco perché hai il {}.

Questo codice crea la sottoclasse anonima concreta, crea un'istanza quindi chiama getType sull'istanza.

+0

scusate, TypeToken non è 'abstract'. Questa è la dichiarazione: 'publicType TypeToken {...}'. – Judking

+0

Bene, non in tutte le versioni. Vedere il link nella mia risposta: 'classe astratta pubblica TypeToken {' ​​ –

+0

Vedo .. ma come spiegare per la mia versione, il costruttore predefinito è 'protected', cosa fanno le parentesi in questo senario? Quindi la coppia può usare per una 'classe non abst' solo per creare una' classe anonima'? Grazie fratello. – Judking

4

new TypeToken<Collection<Integer>>(){} significa che si sta creando un anonymous inner class che si estende TypeToken<Collection<Integer>>. Allo stesso tempo stai creando un'istanza di quella classe anonima.

Dal link:

classi anonimi consentono di rendere il codice più conciso. Ti consentono di dichiarare e creare un'istanza di una classe allo stesso tempo. Sono come le classi locali tranne che non hanno un nome. Usali se hai bisogno di usare una classe locale solo una volta.