2012-04-25 4 views
6

Questo viene implementato come segue (jdk1.6.0_31):Java: sull'implementazione Collezioni ReverseComparator

private static class ReverseComparator<T> 
implements Comparator<Comparable<Object>>, Serializable { 

// use serialVersionUID from JDK 1.2.2 for interoperability 
private static final long serialVersionUID = 7207038068494060240L; 

    public int compare(Comparable<Object> c1, Comparable<Object> c2) { 
     return c2.compareTo(c1); 
    } 

    private Object readResolve() { return reverseOrder(); } 
} 

Perché non può invece calcolato come segue:

private static class ReverseComparator<T extends Comparable<T>> 
implements Comparator<T>, Serializable { 

// use serialVersionUID from JDK 1.2.2 for interoperability 
private static final long serialVersionUID = 7207038068494060240L; 

    public int compare(T c1, T c2){ 
     return c2.compareTo(c1); 
    } 
    ... 
} 

è solo stile o c'è qualche ragione più profonda?

EDIT: il codice sorgente è mostrata da Sun/Oracle JDK ((jdk1.6.0_31)).

+0

Da dove viene esattamente questo codice? Non lo trovo in JDK, ma ci sono un sacco di altri posti. Nessuno finora ha nemmeno usato i generici. –

+0

L'ho trovato in jdk1.6.0_31, src.zip. – shrini1000

+0

Ma puoi dirmi esattamente dove? Dentro quale classe? –

risposta

1

Credo che sia tutto legato al l'intenzione di fare di ReverseComparator un oggetto singlenton. Poiché l'istanza di singlenton deve essere definita in un contesto statico, non è necessario utilizzare alcun tipo generico.

static final ReverseComparator REVERSE_ORDER = new ReverseComparator(); 

Questo codice genera un avviso di tipo non elaborato.

Come tale, l'attuazione di ReverseComparator, che viene utilizzato solo per questa materia, avrebbe potuto essere come lei ha suggerito o come è stato attuato. Forse hanno scelto l'implementazione corrente perché è più facile da leggere, e perché pensavano che l'ulteriore generalizzazione non era necessaria se si è solo andando a essere privatamente utilizzati per questo semplice scopo.

Esecuzione del decompilatore Java sopra l'implementazione e sull'esecuzione del Oracle produce gli stessi codici di byte di tipo grezzo.

public int compare(java.lang.Comparable, java.lang.Comparable 
public int compare(java.lang.Object, java.lang.Object); 

Alla fine, quando il comparatore viene esposta attraverso l'interfaccia pubblica della classe Collections nel metodo reverseOrder(), è impossibile evitare la fusione e l'avviso incontrollato. Ma siamo tutti sicuri che questo non può fallire, indipendentemente dai tipi coinvolti.

Linea di fondo, IMHO Credo che l'unica ragione per la quale è stato implementato come è stato ha a che fare con il codice di chiarezza, o con il desiderio di non complicare le cose più del necessario se, in ogni modo, l'avvertimento incontrollato non poteva essere evitato . Ma hey, questa non sarebbe la prima volta che mi sbaglio ;-)

+0

Sono d'accordo con te sul fatto che non è necessaria un'ulteriore generalizzazione perché la classe è usata privatamente. In effetti, non penso che nessuna generalizzazione sia possibile perché non c'è una classe in Java abbastanza generale che implementa Comparable in modo che possa essere usata come argomento di tipo in un tipo parametrico. Quindi il mio sentimento è che lo è più simile a un avanzo residuo da un codice precedente. – shrini1000

1

solo indovinare, ma è memorizzato in un campo statico

static final ReverseComparator REVERSE_ORDER 
      = new ReverseComparator(); 

così la versione genererebbe un avvertimento 'tipi prime.

+0

Bene, ottengo quell'avvertimento anche con ReverseComparator di Java (dato che dichiara 'T' nella sua definizione) se copio-incollo quella classe nella mia classe e la istanzio staticamente. – shrini1000

+0

Hmm, nella mia fonte è solo 'classe statica privata ReverseComparator' (no' T') – artbristol

+0

jdk1.6.0_31 o qualche altra versione? – shrini1000

1

sto guardando Oracle 1.6.0_26, ma vedo lo stesso codice. Per quanto posso dire, quelli sono funzionalmente equivalenti. Si potrebbe anche potenzialmente scrivere in questo modo:

private static class ReverseComparator<T> implements Comparator<Comparable<T>>, Serializable { 

    // use serialVersionUID from JDK 1.2.2 for interoperability 
    private static final long serialVersionUID = 7207038068494060240L; 

    public int compare(Comparable<T> c1, Comparable<T> c2) { 
     return c2.compareTo((T) c1); 
    } 

    private Object readResolve() { 
     return reverseOrder(); 
    } 
} 

mia unica ipotesi sul motivo per cui lo hanno fatto usando Comparable<Object> si basa sul fatto che le classi che implementano Comparable (o Comparator) devono rispettare il contratto equals(), che fa utilizza Object. Quindi semanticamente, questo sottolinea quella connessione. Oltre a questo, non riesco a pensare a una ragione per cui.