2013-10-21 5 views
65

Ho appena eseguito l'implementazione della classe java.util.Collections di Java 7 e ho visto qualcosa che non capisco. Nella firma della funzione max, perché T è limitato da Object?Perché T è limitato da Object nella firma Collections.max()?

public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll) { 
    Iterator<? extends T> i = coll.iterator(); 
    T candidate = i.next(); 

    while (i.hasNext()) { 
     T next = i.next(); 
     if (next.compareTo(candidate) > 0) 
      candidate = next; 
    } 
    return candidate; 
} 

max sembra funzionare correttamente se il limite dell'oggetto viene omesso.

public static <T extends Comparable<? super T>> T max(Collection<? extends T> coll) { 
    Iterator<? extends T> i = coll.iterator(); 
    T candidate = i.next(); 

    while (i.hasNext()) { 
     T next = i.next(); 
     if (next.compareTo(candidate) > 0) 
      candidate = next; 
    } 
    return candidate; 
} 

Esistono effettivamente situazioni in cui il limite fa la differenza? In caso affermativo, fornire un esempio concreto.

+4

duplicato del [ vs ] (http://stackoverflow.com/questions/10339338/t-extends-object-e-vs-t-extends-e), anche se questo post ha sia una migliore domanda che una risposta. –

risposta

77

I due hanno gli stessi limiti ma lo è una sottile differenza.

<T extends Object & Comparable<? super T>> 

Questo farà sì che T per diventare un Object sotto cancellatura.

<T extends Comparable<? super T>> 

Questo farà sì che T a diventare Comparable sotto cancellatura.


In questo caso si è fatto perché .max anteriore Java 5. Possiamo vedere in this link Joachim gentilmente a condizione che la firma del .max in Java 1.4.2 è:

public static Object max(Collection coll) 

avessimo usato <T extends Comparable<? super T>> come limite, la nostra firma sarebbe

public static Comparable max(Collection coll) 

Quale interromperà le API. Sono riuscito a trovare this page che discute la conversione di vecchie API in quelle generiche e fornisce .max come esempio specifico.

Qui spiegano il motivo per cui max si definisce in questo modo:

È inoltre necessario garantire che l'API rivisto mantiene la compatibilità binaria con i vecchi clienti. Ciò implica che la cancellazione dell'API deve essere uguale all'API originale non generata. Nella maggior parte dei casi, questo cade naturalmente, ma ci sono alcuni casi sottili. Esamineremo uno dei casi più sottili che abbiamo riscontrato, il metodo Collections.max(). Come abbiamo visto nella sezione più divertente con caratteri jolly, una firma plausibile per max() è:

public static <T extends Comparable<? super T>> T max(Collection<T> coll) Questo va bene, se non che la cancellazione di questa firma è: public static Comparable max(Collection coll) che è diverso da quello della firma originale di max(): public static Object max(Collection coll)

Uno potrebbe aver specificato questa firma per max(), ma non è stato fatto, e tutti i vecchi file di classe binario che chiamano Collections.max() dipendono da una firma che restituisce Object.

+0

C'è una ragione per cui sarebbe auspicabile? – templatetypedef

+0

Forse perché ['Collection.max' è precedente a Java 5] (http://docs.oracle.it/javase/1.4.2/docs/api/java/util/Collections.html # max (java.util.Collection)) e come tale precede Generics. E poiché il valore di ritorno è 'T' ciò cambierebbe la firma del metodo dopo la cancellazione. –

+0

@templatetypedef Sì, principalmente nel vecchio codice. Dal momento che Java non ha sempre avuto Generics che ha la firma del metodo dopo che la cancellazione rimane la stessa della firma prima che la sua generazione sia desiderabile. Ricordo di aver letto su docs.oracle.com - mi ci vorrà un po 'di più per trovarlo. –

Problemi correlati